diff --git a/package.json b/package.json index f39f679..059e1c4 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,9 @@ "@sveltejs/vite-plugin-svelte": "^6.2.0", "@tailwindcss/typography": "^0.5.16", "@tailwindcss/vite": "^4.1.13", + "@threlte/core": "^8.3.1", + "@threlte/extras": "^9.7.1", + "@types/three": "^0.182.0", "@typescript-eslint/eslint-plugin": "^8.44.0", "@typescript-eslint/parser": "^8.44.0", "bits-ui": "^2.9.9", @@ -38,6 +41,7 @@ "globals": "^17.3.0", "lottie-web": "^5.13.0", "playwright": "1.58.2", + "postprocessing": "^6.38.2", "prettier": "^3.6.2", "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.7.2", @@ -48,6 +52,7 @@ "svelte-sitemap": "^2.8.0", "svgo": "^4.0.0", "tailwindcss": "^4.1.13", + "three": "0.182.0", "tslib": "^2.8.1", "tsx": "^4.21.0", "typescript": "^5.9.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 98b0794..653dd19 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,15 @@ importers: '@tailwindcss/vite': specifier: ^4.1.13 version: 4.2.1(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)) + '@threlte/core': + specifier: ^8.3.1 + version: 8.3.1(svelte@5.53.6)(three@0.182.0) + '@threlte/extras': + specifier: ^9.7.1 + version: 9.7.1(@types/three@0.182.0)(svelte@5.53.6)(three@0.182.0) + '@types/three': + specifier: ^0.182.0 + version: 0.182.0 '@typescript-eslint/eslint-plugin': specifier: ^8.44.0 version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3) @@ -68,6 +77,9 @@ importers: playwright: specifier: 1.58.2 version: 1.58.2 + postprocessing: + specifier: ^6.38.2 + version: 6.38.2(three@0.182.0) prettier: specifier: ^3.6.2 version: 3.8.1 @@ -98,6 +110,9 @@ importers: tailwindcss: specifier: ^4.1.13 version: 4.2.1 + three: + specifier: 0.182.0 + version: 0.182.0 tslib: specifier: ^2.8.1 version: 2.8.1 @@ -176,6 +191,9 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + '@emnapi/runtime@1.8.1': resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} @@ -1081,6 +1099,26 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@threejs-kit/instanced-sprite-mesh@2.5.1': + resolution: {integrity: sha512-pmt1ALRhbHhCJQTj2FuthH6PeLIeaM4hOuS2JO3kWSwlnvx/9xuUkjFR3JOi/myMqsH7pSsLIROSaBxDfttjeA==} + peerDependencies: + three: '>=0.170.0' + + '@threlte/core@8.3.1': + resolution: {integrity: sha512-qKjjNCQ+40hyeBcfOMh/8ef5x/j5PG5Wmo/L9Ye0aDCcdD6fCewWxfp7tV/J3CxPzX1dEp1JGK7sjyc7ntZSrg==} + peerDependencies: + svelte: '>=5' + three: '>=0.160' + + '@threlte/extras@9.7.1': + resolution: {integrity: sha512-SGm59HDCdHxADFHuweHfFDknwubkCPodyK0pbfsVtOWWOX26gE2xfK7aKolh6YFDiPAjWjGxN0jIgkNbbr1ohg==} + peerDependencies: + svelte: '>=5' + three: '>=0.160' + + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -1090,9 +1128,18 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + + '@types/three@0.182.0': + resolution: {integrity: sha512-WByN9V3Sbwbe2OkWuSGyoqQO8Du6yhYaXtXLoA5FkKTUJorZ+yOHBZ35zUUPQXlAKABZmbYp5oAqpA4RBjtJ/Q==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + '@typescript-eslint/eslint-plugin@8.56.1': resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1152,6 +1199,9 @@ packages: resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@webgpu/types@0.1.68': + resolution: {integrity: sha512-3ab1B59Ojb6RwjOspYLsTpCzbNB3ZaamIAxBMmvnNkiDoLTZUOBXZ9p5nAYVEkQlDdf6qAZWi1pqj9+ypiqznA==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1187,6 +1237,9 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bits-ui@2.16.2: resolution: {integrity: sha512-bgEpRRF7Ck9nRP1pbuKVxpaSMrz+8Pm0y+dmuvlkrSe+uUwIQECef29y6eslFHM6pCAubUh7STrsTLUUp8fzFQ==} engines: {node: '>=20'} @@ -1215,6 +1268,12 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camera-controls@3.1.2: + resolution: {integrity: sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==} + engines: {node: '>=22.0.0', npm: '>=10.5.1'} + peerDependencies: + three: '>=0.126.1' + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1313,6 +1372,9 @@ packages: devalue@5.6.3: resolution: {integrity: sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==} + diet-sprite@0.0.1: + resolution: {integrity: sha512-zSHI2WDAn1wJqJYxcmjWfJv3Iw8oL9reQIbEyx2x2/EZ4/qmUTIo8/5qOCurnAcq61EwtJJaZ0XTy2NRYqpB5A==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -1326,6 +1388,9 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + earcut@2.2.4: + resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} + enhanced-resolve@5.20.0: resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} engines: {node: '>=10.13.0'} @@ -1453,6 +1518,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -1679,6 +1747,12 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + maath@0.10.8: + resolution: {integrity: sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==} + peerDependencies: + '@types/three': '>=0.134.0' + three: '>=0.134.0' + magic-string@0.30.18: resolution: {integrity: sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==} @@ -1698,6 +1772,9 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + meshoptimizer@0.22.0: + resolution: {integrity: sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -1717,6 +1794,9 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1833,6 +1913,11 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + postprocessing@6.38.2: + resolution: {integrity: sha512-7DwuT7Tkst41ZjSj287g7C9c5/D3Xx5rMgBosg0dadbUPoZD2HNzkadKPol1d2PJAoI9f+Jeh1/v9YfLzpFGVw==} + peerDependencies: + three: '>= 0.157.0 < 0.183.0' + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -1918,6 +2003,10 @@ packages: resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} engines: {node: '>=8'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2066,6 +2155,29 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + three-instanced-uniforms-mesh@0.52.4: + resolution: {integrity: sha512-YwDBy05hfKZQtU+Rp0KyDf9yH4GxfhxMbVt9OYruxdgLfPwmDG5oAbGoW0DrKtKZSM3BfFcCiejiOHCjFBTeng==} + peerDependencies: + three: '>=0.125.0' + + three-mesh-bvh@0.9.5: + resolution: {integrity: sha512-MYpwzUWDxPAKGhSBFin9E/7K4AAHyIm4IfMZQ/3+Z/jq/swa2dAhXx0yUNDd9mjlhLuzXkMBTGDZioL2GSlIfQ==} + peerDependencies: + three: '>= 0.159.0' + + three-perf@1.0.11: + resolution: {integrity: sha512-OgBpZjwL+csQKGKZjpkH/QHdbGFMxqngMbSEJeSnVNfXDYd6On7WHNv/GhUZH4YxIpNMwMahBWrNnsJvnbSJHQ==} + peerDependencies: + three: '>=0.170' + + three-viewport-gizmo@2.2.0: + resolution: {integrity: sha512-Jo9Liur1rUmdKk75FZumLU/+hbF+RtJHi1qsKZpntjKlCYScK6tjbYoqvJ9M+IJphrlQJF5oReFW7Sambh0N4Q==} + peerDependencies: + three: '>=0.162.0 <1.0.0' + + three@0.182.0: + resolution: {integrity: sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -2078,6 +2190,19 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + troika-three-text@0.52.4: + resolution: {integrity: sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==} + peerDependencies: + three: '>=0.125.0' + + troika-three-utils@0.52.4: + resolution: {integrity: sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==} + peerDependencies: + three: '>=0.125.0' + + troika-worker-utils@0.52.0: + resolution: {integrity: sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==} + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} @@ -2092,6 +2217,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tweakpane@3.1.10: + resolution: {integrity: sha512-rqwnl/pUa7+inhI2E9ayGTqqP0EPOOn/wVvSWjZsRbZUItzNShny7pzwL3hVlaN4m9t/aZhsP0aFQ9U5VVR2VQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2173,6 +2301,9 @@ packages: vite: optional: true + webgl-sdf-generator@1.1.1: + resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2270,6 +2401,8 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@dimforge/rapier3d-compat@0.12.0': {} + '@emnapi/runtime@1.8.1': dependencies: tslib: 2.8.1 @@ -2931,14 +3064,60 @@ snapshots: tailwindcss: 4.2.1 vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0) + '@threejs-kit/instanced-sprite-mesh@2.5.1(@types/three@0.182.0)(three@0.182.0)': + dependencies: + diet-sprite: 0.0.1 + earcut: 2.2.4 + maath: 0.10.8(@types/three@0.182.0)(three@0.182.0) + three: 0.182.0 + three-instanced-uniforms-mesh: 0.52.4(three@0.182.0) + troika-three-utils: 0.52.4(three@0.182.0) + transitivePeerDependencies: + - '@types/three' + + '@threlte/core@8.3.1(svelte@5.53.6)(three@0.182.0)': + dependencies: + mitt: 3.0.1 + svelte: 5.53.6 + three: 0.182.0 + + '@threlte/extras@9.7.1(@types/three@0.182.0)(svelte@5.53.6)(three@0.182.0)': + dependencies: + '@threejs-kit/instanced-sprite-mesh': 2.5.1(@types/three@0.182.0)(three@0.182.0) + camera-controls: 3.1.2(three@0.182.0) + svelte: 5.53.6 + three: 0.182.0 + three-mesh-bvh: 0.9.5(three@0.182.0) + three-perf: 1.0.11(three@0.182.0) + three-viewport-gizmo: 2.2.0(three@0.182.0) + troika-three-text: 0.52.4(three@0.182.0) + transitivePeerDependencies: + - '@types/three' + + '@tweenjs/tween.js@23.1.3': {} + '@types/cookie@0.6.0': {} '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} + '@types/stats.js@0.17.4': {} + + '@types/three@0.182.0': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + '@webgpu/types': 0.1.68 + fflate: 0.8.2 + meshoptimizer: 0.22.0 + '@types/trusted-types@2.0.7': {} + '@types/webxr@0.5.24': {} + '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -3030,6 +3209,8 @@ snapshots: '@typescript-eslint/types': 8.56.1 eslint-visitor-keys: 5.0.1 + '@webgpu/types@0.1.68': {} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -3057,6 +3238,10 @@ snapshots: balanced-match@4.0.4: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + bits-ui@2.16.2(@internationalized/date@3.8.0)(@sveltejs/kit@2.53.4(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.6)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)))(svelte@5.53.6)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)))(svelte@5.53.6): dependencies: '@floating-ui/core': 1.7.3 @@ -3089,6 +3274,10 @@ snapshots: callsites@3.1.0: {} + camera-controls@3.1.2(three@0.182.0): + dependencies: + three: 0.182.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -3164,6 +3353,8 @@ snapshots: devalue@5.6.3: {} + diet-sprite@0.0.1: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -3182,6 +3373,8 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 + earcut@2.2.4: {} + enhanced-resolve@5.20.0: dependencies: graceful-fs: 4.2.11 @@ -3382,6 +3575,8 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fflate@0.8.2: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -3551,6 +3746,11 @@ snapshots: lz-string@1.5.0: {} + maath@0.10.8(@types/three@0.182.0)(three@0.182.0): + dependencies: + '@types/three': 0.182.0 + three: 0.182.0 + magic-string@0.30.18: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3569,6 +3769,8 @@ snapshots: merge2@1.4.1: {} + meshoptimizer@0.22.0: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -3596,6 +3798,8 @@ snapshots: minimist@1.2.8: {} + mitt@3.0.1: {} + mri@1.2.0: {} mrmime@2.0.1: {} @@ -3688,6 +3892,10 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postprocessing@6.38.2(three@0.182.0): + dependencies: + three: 0.182.0 + prelude-ls@1.2.1: {} prettier-plugin-svelte@3.5.0(prettier@3.8.1)(svelte@5.53.6): @@ -3711,6 +3919,8 @@ snapshots: regexparam@3.0.0: {} + require-from-string@2.0.2: {} + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -3911,6 +4121,27 @@ snapshots: tapable@2.3.0: {} + three-instanced-uniforms-mesh@0.52.4(three@0.182.0): + dependencies: + three: 0.182.0 + troika-three-utils: 0.52.4(three@0.182.0) + + three-mesh-bvh@0.9.5(three@0.182.0): + dependencies: + three: 0.182.0 + + three-perf@1.0.11(three@0.182.0): + dependencies: + three: 0.182.0 + troika-three-text: 0.52.4(three@0.182.0) + tweakpane: 3.1.10 + + three-viewport-gizmo@2.2.0(three@0.182.0): + dependencies: + three: 0.182.0 + + three@0.182.0: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -3922,6 +4153,20 @@ snapshots: totalist@3.0.1: {} + troika-three-text@0.52.4(three@0.182.0): + dependencies: + bidi-js: 1.0.3 + three: 0.182.0 + troika-three-utils: 0.52.4(three@0.182.0) + troika-worker-utils: 0.52.0 + webgl-sdf-generator: 1.1.1 + + troika-three-utils@0.52.4(three@0.182.0): + dependencies: + three: 0.182.0 + + troika-worker-utils@0.52.0: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -3935,6 +4180,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tweakpane@3.1.10: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -3990,6 +4237,8 @@ snapshots: optionalDependencies: vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0) + webgl-sdf-generator@1.1.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 diff --git a/src/lib/components/ModelViewer/Environment.svelte b/src/lib/components/ModelViewer/Environment.svelte new file mode 100644 index 0000000..856481e --- /dev/null +++ b/src/lib/components/ModelViewer/Environment.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ModelViewer/Model.svelte b/src/lib/components/ModelViewer/Model.svelte new file mode 100644 index 0000000..9b7e1e4 --- /dev/null +++ b/src/lib/components/ModelViewer/Model.svelte @@ -0,0 +1,42 @@ + + + diff --git a/src/lib/components/ModelViewer/ModelViewer.svelte b/src/lib/components/ModelViewer/ModelViewer.svelte new file mode 100644 index 0000000..df314b0 --- /dev/null +++ b/src/lib/components/ModelViewer/ModelViewer.svelte @@ -0,0 +1,48 @@ + + +
+
+ + + + + + + + + + + +
+
+ L O A D I N G +
+
diff --git a/src/lib/components/ModelViewer/Renderer.svelte b/src/lib/components/ModelViewer/Renderer.svelte new file mode 100644 index 0000000..6dc4bea --- /dev/null +++ b/src/lib/components/ModelViewer/Renderer.svelte @@ -0,0 +1,65 @@ + diff --git a/src/lib/images/hdri/day.hdr b/src/lib/images/hdri/day.hdr new file mode 100644 index 0000000..9fde3e0 Binary files /dev/null and b/src/lib/images/hdri/day.hdr differ diff --git a/src/lib/images/hdri/night.hdr b/src/lib/images/hdri/night.hdr new file mode 100644 index 0000000..88cc041 Binary files /dev/null and b/src/lib/images/hdri/night.hdr differ diff --git a/src/lib/interests.ts b/src/lib/interests.ts new file mode 100644 index 0000000..e706233 --- /dev/null +++ b/src/lib/interests.ts @@ -0,0 +1,34 @@ +export interface Interest { + description: string; + id: string; + models: string[]; + name: string; +} + +const interestsWithoutModels = [ + { description: "", id: "cubing", name: "Cubing" }, + { + description: "", + id: "gaming", + name: "Gaming", + }, + { + description: "", + id: "music", + name: "Music", + }, +] as const satisfies readonly Omit[]; + +const interestModels: Record = import.meta.glob("./*/*.glb", { + base: "./models/interests", + eager: true, + import: "default", + query: "url", +}); + +export const interests = interestsWithoutModels.map((interest) => ({ + ...interest, + models: Object.entries(interestModels) + .filter(([name]) => name.includes(interest.id)) + .map(([, model]) => model), +})); diff --git a/src/lib/links.ts b/src/lib/links.ts index 9f2e48a..f638350 100644 --- a/src/lib/links.ts +++ b/src/lib/links.ts @@ -2,4 +2,7 @@ import type { RouteId } from "$app/types"; export const label = (link: RouteId) => link.replaceAll(/-+|\//g, " ").trim(); -export const links = ["/projects"] as const satisfies readonly RouteId[]; +export const links = [ + "/interests", + "/projects", +] as const satisfies readonly RouteId[]; diff --git a/src/lib/models/interests/cubing/rubiks.glb b/src/lib/models/interests/cubing/rubiks.glb new file mode 100644 index 0000000..f035e8d Binary files /dev/null and b/src/lib/models/interests/cubing/rubiks.glb differ diff --git a/src/lib/models/interests/gaming/heartcontainer.glb b/src/lib/models/interests/gaming/heartcontainer.glb new file mode 100644 index 0000000..bab438c Binary files /dev/null and b/src/lib/models/interests/gaming/heartcontainer.glb differ diff --git a/src/lib/models/interests/gaming/hk-nail.glb b/src/lib/models/interests/gaming/hk-nail.glb new file mode 100644 index 0000000..ca98653 Binary files /dev/null and b/src/lib/models/interests/gaming/hk-nail.glb differ diff --git a/src/lib/models/interests/gaming/hylianshield.glb b/src/lib/models/interests/gaming/hylianshield.glb new file mode 100644 index 0000000..29f5dd1 Binary files /dev/null and b/src/lib/models/interests/gaming/hylianshield.glb differ diff --git a/src/lib/models/interests/gaming/mastersword.glb b/src/lib/models/interests/gaming/mastersword.glb new file mode 100644 index 0000000..3f8a840 Binary files /dev/null and b/src/lib/models/interests/gaming/mastersword.glb differ diff --git a/src/lib/models/interests/gaming/modelrocket.glb b/src/lib/models/interests/gaming/modelrocket.glb new file mode 100644 index 0000000..adacd69 Binary files /dev/null and b/src/lib/models/interests/gaming/modelrocket.glb differ diff --git a/src/lib/models/interests/gaming/solanummask.glb b/src/lib/models/interests/gaming/solanummask.glb new file mode 100644 index 0000000..6dd6a95 Binary files /dev/null and b/src/lib/models/interests/gaming/solanummask.glb differ diff --git a/src/lib/models/interests/gaming/triforce.glb b/src/lib/models/interests/gaming/triforce.glb new file mode 100644 index 0000000..fe94dc4 Binary files /dev/null and b/src/lib/models/interests/gaming/triforce.glb differ diff --git a/src/lib/random.ts b/src/lib/random.ts new file mode 100644 index 0000000..51853e4 --- /dev/null +++ b/src/lib/random.ts @@ -0,0 +1,9 @@ +export const random = () => Math.random(); + +export const randomInt = (min: number, max: number) => + Math.floor(random() * (max - min)) + min; + +export const randomBool = () => random() < 0.5; + +export const randomElement = (array: T[]) => + array[randomInt(0, array.length)]; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index cdbd987..27b1efb 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -48,7 +48,7 @@
- {#key page.url.pathname} + {#key page.route.id}
+ import { resolve } from "$app/paths"; + import { page } from "$app/state"; + import Page from "$lib/components/Page.svelte"; + import { interests } from "$lib/interests"; + + let { children } = $props(); + + + + + + {@render children?.()} + diff --git a/src/routes/interests/+page.ts b/src/routes/interests/+page.ts new file mode 100644 index 0000000..9738a01 --- /dev/null +++ b/src/routes/interests/+page.ts @@ -0,0 +1,12 @@ +import { redirect } from "@sveltejs/kit"; +import { resolve } from "$app/paths"; +import { interests } from "$lib/interests"; +import { randomElement } from "$lib/random"; + +import type { PageLoad } from "./$types"; + +export const load: PageLoad = () => { + const interest = randomElement(interests); + + redirect(308, resolve("/interests/[interest]", { interest: interest.id })); +}; diff --git a/src/routes/interests/[interest]/+page.svelte b/src/routes/interests/[interest]/+page.svelte new file mode 100644 index 0000000..4503fff --- /dev/null +++ b/src/routes/interests/[interest]/+page.svelte @@ -0,0 +1,11 @@ + + +
+

{data.interest.description}

+
+ + diff --git a/src/routes/interests/[interest]/+page.ts b/src/routes/interests/[interest]/+page.ts new file mode 100644 index 0000000..90dc40f --- /dev/null +++ b/src/routes/interests/[interest]/+page.ts @@ -0,0 +1,20 @@ +import { error } from "@sveltejs/kit"; +import { type Interest, interests } from "$lib/interests"; +import { randomElement } from "$lib/random"; + +import type { PageLoad } from "./$types"; + +export const load: PageLoad = ({ params }) => { + const interest: Interest | undefined = interests.find( + (i) => i.id === params.interest, + ); + + if (!interest) throw error(404, "Interest not found"); + + const model = randomElement(interest.models); + + return { + interest, + model, + }; +};