diff --git a/package-lock.json b/package-lock.json index 74b6e6c6..4cf57781 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,11 +29,11 @@ "eslint-import-resolver-typescript": "^3.7.0", "globals": "^15.13.0", "i18next": "^24.0.5", - "i18next-browser-languagedetector": "^8.0.0", + "i18next-browser-languagedetector": "^8.0.2", "jest": "^29.7.0", - "playcanvas": "^2.3.1", + "playcanvas": "^2.3.3", "postcss": "^8.4.49", - "rollup": "^4.28.0", + "rollup": "^4.28.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-visualizer": "^5.12.0", "sass": "^1.82.0", @@ -501,9 +501,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.3.tgz", - "integrity": "sha512-yTmc8J+Sj8yLzwr4PD5Xb/WF3bOYu2C2OoSZPzbuqRm4n98XirsbzaX+GloeO376UnSYIYJ4NCanwV5/ugZkwA==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.26.2", @@ -1783,9 +1783,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz", - "integrity": "sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", + "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", "cpu": [ "arm" ], @@ -1796,9 +1796,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz", - "integrity": "sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", + "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", "cpu": [ "arm64" ], @@ -1809,9 +1809,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz", - "integrity": "sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", + "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", "cpu": [ "arm64" ], @@ -1822,9 +1822,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz", - "integrity": "sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", + "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", "cpu": [ "x64" ], @@ -1835,9 +1835,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz", - "integrity": "sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", + "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", "cpu": [ "arm64" ], @@ -1848,9 +1848,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz", - "integrity": "sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", + "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", "cpu": [ "x64" ], @@ -1861,9 +1861,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz", - "integrity": "sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", + "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", "cpu": [ "arm" ], @@ -1874,9 +1874,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz", - "integrity": "sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", + "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", "cpu": [ "arm" ], @@ -1887,9 +1887,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz", - "integrity": "sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", + "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", "cpu": [ "arm64" ], @@ -1900,9 +1900,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz", - "integrity": "sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", + "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", "cpu": [ "arm64" ], @@ -1912,10 +1912,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", + "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz", - "integrity": "sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", + "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", "cpu": [ "ppc64" ], @@ -1926,9 +1939,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz", - "integrity": "sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", + "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", "cpu": [ "riscv64" ], @@ -1939,9 +1952,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz", - "integrity": "sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", + "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", "cpu": [ "s390x" ], @@ -1952,9 +1965,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz", - "integrity": "sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", "cpu": [ "x64" ], @@ -1965,9 +1978,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz", - "integrity": "sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", + "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", "cpu": [ "x64" ], @@ -1978,9 +1991,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz", - "integrity": "sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", + "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", "cpu": [ "arm64" ], @@ -1991,9 +2004,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz", - "integrity": "sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", + "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", "cpu": [ "ia32" ], @@ -2004,9 +2017,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz", - "integrity": "sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", + "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", "cpu": [ "x64" ], @@ -3026,16 +3039,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -3044,6 +3056,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3075,9 +3100,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", "dev": true, "funding": [ { @@ -3697,9 +3722,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -3892,6 +3917,20 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dunder-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", + "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3899,9 +3938,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.70", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.70.tgz", - "integrity": "sha512-P6FPqAWIZrC3sHDAwBitJBs7N7IF58m39XVny7DFseQXK2eiMn7nNQizFf63mWDDUnFvaqsM8FI0+ZZfLkdUGA==", + "version": "1.5.71", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.71.tgz", + "integrity": "sha512-dB68l59BI75W1BUGVTAEJy45CEVuEGy9qPVVQ8pnHyHMn36PLPPoE1mjLH+lo9rKulO3HC2OhbACI/8tCqJBcA==", "dev": true }, "node_modules/emittery": { @@ -4014,13 +4053,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -4807,16 +4843,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.5.tgz", + "integrity": "sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==", "dev": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -5013,12 +5052,12 @@ } }, "node_modules/has-proto": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", - "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "dunder-proto": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -5113,9 +5152,9 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", - "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz", + "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==", "dev": true, "dependencies": { "@babel/runtime": "^7.23.2" @@ -7240,9 +7279,9 @@ } }, "node_modules/playcanvas": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/playcanvas/-/playcanvas-2.3.1.tgz", - "integrity": "sha512-jXWj5spsRp1GaQwV+43W17eVwkqWg8XDNH8aZwqdBghEfBpj9KWPeXJP2Gc0/jOWLutZ1qD1cvEyRypaaByZfg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/playcanvas/-/playcanvas-2.3.3.tgz", + "integrity": "sha512-0Lzq5wJliAQ9NmU//pK6HPW/S3x95/z4Z/cOpPcX0qYbePESUyZupcViOVsclXW0SEKBnEzRjNuWAtgMw1kraA==", "dev": true, "dependencies": { "@types/webxr": "^0.5.16", @@ -8022,18 +8061,19 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", - "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", + "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", + "dunder-proto": "^1.0.0", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "which-builtin-type": "^1.1.4" + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.0" }, "engines": { "node": ">= 0.4" @@ -8195,9 +8235,9 @@ } }, "node_modules/rollup": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.0.tgz", - "integrity": "sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", + "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", "dev": true, "dependencies": { "@types/estree": "1.0.6" @@ -8210,24 +8250,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.28.0", - "@rollup/rollup-android-arm64": "4.28.0", - "@rollup/rollup-darwin-arm64": "4.28.0", - "@rollup/rollup-darwin-x64": "4.28.0", - "@rollup/rollup-freebsd-arm64": "4.28.0", - "@rollup/rollup-freebsd-x64": "4.28.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.28.0", - "@rollup/rollup-linux-arm-musleabihf": "4.28.0", - "@rollup/rollup-linux-arm64-gnu": "4.28.0", - "@rollup/rollup-linux-arm64-musl": "4.28.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.28.0", - "@rollup/rollup-linux-riscv64-gnu": "4.28.0", - "@rollup/rollup-linux-s390x-gnu": "4.28.0", - "@rollup/rollup-linux-x64-gnu": "4.28.0", - "@rollup/rollup-linux-x64-musl": "4.28.0", - "@rollup/rollup-win32-arm64-msvc": "4.28.0", - "@rollup/rollup-win32-ia32-msvc": "4.28.0", - "@rollup/rollup-win32-x64-msvc": "4.28.0", + "@rollup/rollup-android-arm-eabi": "4.28.1", + "@rollup/rollup-android-arm64": "4.28.1", + "@rollup/rollup-darwin-arm64": "4.28.1", + "@rollup/rollup-darwin-x64": "4.28.1", + "@rollup/rollup-freebsd-arm64": "4.28.1", + "@rollup/rollup-freebsd-x64": "4.28.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", + "@rollup/rollup-linux-arm-musleabihf": "4.28.1", + "@rollup/rollup-linux-arm64-gnu": "4.28.1", + "@rollup/rollup-linux-arm64-musl": "4.28.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", + "@rollup/rollup-linux-riscv64-gnu": "4.28.1", + "@rollup/rollup-linux-s390x-gnu": "4.28.1", + "@rollup/rollup-linux-x64-gnu": "4.28.1", + "@rollup/rollup-linux-x64-musl": "4.28.1", + "@rollup/rollup-win32-arm64-msvc": "4.28.1", + "@rollup/rollup-win32-ia32-msvc": "4.28.1", + "@rollup/rollup-win32-x64-msvc": "4.28.1", "fsevents": "~2.3.2" } }, diff --git a/package.json b/package.json index bed540bb..615dfc1c 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,11 @@ "eslint-import-resolver-typescript": "^3.7.0", "globals": "^15.13.0", "i18next": "^24.0.5", - "i18next-browser-languagedetector": "^8.0.0", + "i18next-browser-languagedetector": "^8.0.2", "jest": "^29.7.0", - "playcanvas": "^2.3.1", + "playcanvas": "^2.3.3", "postcss": "^8.4.49", - "rollup": "^4.28.0", + "rollup": "^4.28.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-visualizer": "^5.12.0", "sass": "^1.82.0", diff --git a/src/shaders/splat-shader.ts b/src/shaders/splat-shader.ts index 40025034..d68b2ea9 100644 --- a/src/shaders/splat-shader.ts +++ b/src/shaders/splat-shader.ts @@ -2,8 +2,6 @@ const vertexShader = /* glsl*/` #include "gsplatCommonVS" uniform sampler2D splatState; -uniform highp usampler2D splatTransform; // per-splat index into transform palette -uniform sampler2D transformPalette; // palette of transform matrices uniform vec4 selectedClr; uniform vec4 lockedClr; @@ -16,106 +14,16 @@ varying mediump vec4 color; mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0); -// calculate 2d covariance vectors -bool projectCenterCustom(SplatState state, vec3 center, out ProjectedState projState, in mat4 modelMat) { - // project center to screen space - mat4 model_view = matrix_view * modelMat; - vec4 centerCam = model_view * vec4(center, 1.0); - vec4 centerProj = matrix_projection * centerCam; - if (centerProj.z < -centerProj.w) { - return false; - } - - // get covariance - vec3 covA, covB; - readCovariance(state, covA, covB); - - mat3 Vrk = mat3( - covA.x, covA.y, covA.z, - covA.y, covB.x, covB.y, - covA.z, covB.y, covB.z - ); - - float focal = viewport.x * matrix_projection[0][0]; - - vec3 v = camera_params.w == 1.0 ? vec3(0.0, 0.0, 1.0) : centerCam.xyz; - float J1 = focal / v.z; - vec2 J2 = -J1 / v.z * v.xy; - mat3 J = mat3( - J1, 0.0, J2.x, - 0.0, J1, J2.y, - 0.0, 0.0, 0.0 - ); - - mat3 W = transpose(mat3(model_view)); - mat3 T = W * J; - mat3 cov = transpose(T) * Vrk * T; - - float diagonal1 = cov[0][0] + 0.3; - float offDiagonal = cov[0][1]; - float diagonal2 = cov[1][1] + 0.3; - - float mid = 0.5 * (diagonal1 + diagonal2); - float radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal)); - float lambda1 = mid + radius; - float lambda2 = max(mid - radius, 0.1); - - float l1 = 2.0 * min(sqrt(2.0 * lambda1), 1024.0); - float l2 = 2.0 * min(sqrt(2.0 * lambda2), 1024.0); - - // early-out gaussians smaller than 2 pixels - if (l1 < 2.0 && l2 < 2.0) { - return false; - } - - // perform clipping test against x/y - if (any(greaterThan(abs(centerProj.xy) - vec2(l1, l2) / viewport * centerProj.w, centerProj.ww))) { - return false; - } - - vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1)); - vec2 v1 = l1 * diagonalVector; - vec2 v2 = l2 * vec2(diagonalVector.y, -diagonalVector.x); - - projState.modelView = model_view; - projState.centerCam = centerCam.xyz; - projState.centerProj = centerProj; - projState.cornerOffset = (state.cornerUV.x * v1 + state.cornerUV.y * v2) / viewport * centerProj.w; - projState.cornerProj = centerProj + vec4(projState.cornerOffset, 0.0, 0.0); - projState.cornerUV = state.cornerUV; - - return true; -} - -mat4 applyPaletteTransform(SplatState state, mat4 model) { - uint transformIndex = texelFetch(splatTransform, state.uv, 0).r; - if (transformIndex == 0u) { - return model; - } - - // read transform matrix - int u = int(transformIndex % 512u) * 3; - int v = int(transformIndex / 512u); - - mat4 t; - t[0] = texelFetch(transformPalette, ivec2(u, v), 0); - t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0); - t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0); - t[3] = vec4(0.0, 0.0, 0.0, 1.0); - - return model * transpose(t); -} - void main(void) { // read gaussian details - SplatState state; - if (!initState(state)) { + SplatSource source; + if (!initSource(source)) { gl_Position = discardVec; return; } // get per-gaussian edit state, discard if deleted - uint vertexState = uint(texelFetch(splatState, state.uv, 0).r * 255.0 + 0.5); + uint vertexState = uint(texelFetch(splatState, source.uv, 0).r * 255.0 + 0.5); #if OUTLINE_PASS if (vertexState != 1u) { @@ -140,35 +48,40 @@ void main(void) { #endif // get center - vec3 center = readCenter(state); + vec3 modelCenter = readCenter(source); + + SplatCenter center; + if (!initCenter(source, modelCenter, center)) { + gl_Position = discardVec; + return; + } - ProjectedState projState; - if (!projectCenterCustom(state, center, projState, applyPaletteTransform(state, matrix_model))) { + SplatCorner corner; + if (!initCorner(source, center, corner)) { gl_Position = discardVec; return; } - // ensure splats aren't clipped by front and back clipping planes - gl_Position = projState.cornerProj; - gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w)); + gl_Position = center.proj + vec4(corner.offset, 0.0, 0.0); // store texture coord and locked state - texCoordIsLocked = vec3(state.cornerUV, (vertexState & 2u) != 0u ? 1.0 : 0.0); + texCoordIsLocked = vec3(corner.uv, (vertexState & 2u) != 0u ? 1.0 : 0.0); #if UNDERLAY_PASS - color = readColor(state); + color = readColor(source); color.xyz = mix(color.xyz, selectedClr.xyz * 0.2, selectedClr.a) * selectedClr.a; #elif PICK_PASS - uvec3 bits = (uvec3(state.id) >> uvec3(0u, 8u, 16u)) & uvec3(255u); - color = vec4(vec3(bits) / 255.0, readColor(state).a); + uvec3 bits = (uvec3(source.id) >> uvec3(0u, 8u, 16u)) & uvec3(255u); + color = vec4(vec3(bits) / 255.0, readColor(source).a); // handle splat color #elif FORWARD_PASS // read color - color = readColor(state); + color = readColor(source); // evaluate spherical harmonics #if SH_BANDS > 0 - color.xyz = max(vec3(0.0), color.xyz + evalSH(state, projState)); + vec3 dir = normalize(center.view * mat3(center.modelView)); + color.xyz += evalSH(source, dir); #endif // apply tint/brightness @@ -234,4 +147,54 @@ void main(void) { } `; -export { vertexShader, fragmentShader }; +const gsplatCenter = /* glsl*/` +uniform mat4 matrix_model; +uniform mat4 matrix_view; +uniform mat4 matrix_projection; + +uniform highp usampler2D splatTransform; // per-splat index into transform palette +uniform sampler2D transformPalette; // palette of transform matrices + +mat4 applyPaletteTransform(SplatSource source, mat4 model) { + uint transformIndex = texelFetch(splatTransform, source.uv, 0).r; + if (transformIndex == 0u) { + return model; + } + + // read transform matrix + int u = int(transformIndex % 512u) * 3; + int v = int(transformIndex / 512u); + + mat4 t; + t[0] = texelFetch(transformPalette, ivec2(u, v), 0); + t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0); + t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0); + t[3] = vec4(0.0, 0.0, 0.0, 1.0); + + return model * transpose(t); +} + +// project the model space gaussian center to view and clip space +bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) { + mat4 modelView = matrix_view * applyPaletteTransform(source, matrix_model); + vec4 centerView = modelView * vec4(modelCenter, 1.0); + + // early out if splat is behind the camear + if (centerView.z > 0.0) { + return false; + } + + vec4 centerProj = matrix_projection * centerView; + + // ensure gaussians are not clipped by camera near and far + centerProj.z = clamp(centerProj.z, -abs(centerProj.w), abs(centerProj.w)); + + center.view = centerView.xyz / centerView.w; + center.proj = centerProj; + center.projMat00 = matrix_projection[0][0]; + center.modelView = modelView; + return true; +} +`; + +export { vertexShader, fragmentShader, gsplatCenter }; diff --git a/src/splat.ts b/src/splat.ts index fae22663..fcc05895 100644 --- a/src/splat.ts +++ b/src/splat.ts @@ -17,7 +17,7 @@ import { import { Element, ElementType } from './element'; import { Serializer } from './serializer'; -import { vertexShader, fragmentShader } from './shaders/splat-shader'; +import { vertexShader, fragmentShader, gsplatCenter } from './shaders/splat-shader'; import { State } from './splat-state'; import { TransformPalette } from './transform-palette'; @@ -77,7 +77,8 @@ class Splat extends Element { // get material options object for a shader that renders with the given number of bands const materialOptions = { vertex: vertexShader, - fragment: fragmentShader + fragment: fragmentShader, + chunks: { gsplatCenterVS: gsplatCenter } }; this.asset = asset; diff --git a/src/templates/viewer-html-template.ts b/src/templates/viewer-html-template.ts index a9cf0f3f..9d912175 100644 --- a/src/templates/viewer-html-template.ts +++ b/src/templates/viewer-html-template.ts @@ -78,11 +78,11 @@ const template = /* html */ ` - +