diff --git a/package.json b/package.json
index bd13ced..7c8da14 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,9 @@
},
"type": "module",
"dependencies": {
+ "@threlte/core": "6.0.0-next.11",
+ "@threlte/extras": "5.0.0-next.16",
"@types/three": "^0.154.0",
- "three": "^0.154.0"
+ "three": "^0.155.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 84c2fd4..089d397 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,12 +5,18 @@ settings:
excludeLinksFromLockfile: false
dependencies:
+ '@threlte/core':
+ specifier: 6.0.0-next.11
+ version: 6.0.0-next.11
+ '@threlte/extras':
+ specifier: 5.0.0-next.16
+ version: 5.0.0-next.16(three@0.155.0)
'@types/three':
specifier: ^0.154.0
version: 0.154.0
three:
- specifier: ^0.154.0
- version: 0.154.0
+ specifier: ^0.155.0
+ version: 0.155.0
devDependencies:
'@skeletonlabs/skeleton':
@@ -486,6 +492,19 @@ packages:
- supports-color
dev: true
+ /@threlte/core@6.0.0-next.11:
+ resolution: {integrity: sha512-mW7tCxUiXTrMvTb9NLD/fBNlMtnSDnIdBykf7bXKw6Jd5lKUGNq1zQp/8jg456g17XJazmAY1nO/oJ54ye1qoA==}
+ dev: false
+
+ /@threlte/extras@5.0.0-next.16(three@0.155.0):
+ resolution: {integrity: sha512-KcjvVrRlvTtHlzHdRtvEHmQa+ijyr6CFLIIN1kISZHvvnReg4HuNOZQRgAfjXCDs8Rrmoq31H9nvcayfEDrIwA==}
+ dependencies:
+ lodash: 4.17.21
+ troika-three-text: 0.47.2(three@0.155.0)
+ transitivePeerDependencies:
+ - three
+ dev: false
+
/@tweenjs/tween.js@18.6.4:
resolution: {integrity: sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==}
dev: false
@@ -751,6 +770,12 @@ packages:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: true
+ /bidi-js@1.0.2:
+ resolution: {integrity: sha512-rzSy/k7WdX5zOyeHHCOixGXbCHkyogkxPKL2r8QtzHmVQDiWCXUWa18bLdMWT9CYMLOYTjWpTHawuev2ouYJVw==}
+ dependencies:
+ require-from-string: 2.0.2
+ dev: false
+
/binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
@@ -1449,6 +1474,10 @@ packages:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true
+ /lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: false
+
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
@@ -1817,6 +1846,11 @@ packages:
picomatch: 2.3.1
dev: true
+ /require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
/resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -2152,8 +2186,8 @@ packages:
any-promise: 1.3.0
dev: true
- /three@0.154.0:
- resolution: {integrity: sha512-Uzz8C/5GesJzv8i+Y2prEMYUwodwZySPcNhuJUdsVMH2Yn4Nm8qlbQe6qRN5fOhg55XB0WiLfTPBxVHxpE60ug==}
+ /three@0.155.0:
+ resolution: {integrity: sha512-sNgCYmDijnIqkD/bMfk+1pHg3YzsxW7V2ChpuP6HCQ8NiZr3RufsXQr8M3SSUMjW4hG+sUk7YbyuY0DncaDTJQ==}
dev: false
/to-regex-range@5.0.1:
@@ -2168,6 +2202,30 @@ packages:
engines: {node: '>=6'}
dev: true
+ /troika-three-text@0.47.2(three@0.155.0):
+ resolution: {integrity: sha512-qylT0F+U7xGs+/PEf3ujBdJMYWbn0Qci0kLqI5BJG2kW1wdg4T1XSxneypnF05DxFqJhEzuaOR9S2SjiyknMng==}
+ peerDependencies:
+ three: '>=0.125.0'
+ dependencies:
+ bidi-js: 1.0.2
+ three: 0.155.0
+ troika-three-utils: 0.47.2(three@0.155.0)
+ troika-worker-utils: 0.47.2
+ webgl-sdf-generator: 1.1.1
+ dev: false
+
+ /troika-three-utils@0.47.2(three@0.155.0):
+ resolution: {integrity: sha512-/28plhCxfKtH7MSxEGx8e3b/OXU5A0xlwl+Sbdp0H8FXUHKZDoksduEKmjQayXYtxAyuUiCRunYIv/8Vi7aiyg==}
+ peerDependencies:
+ three: '>=0.125.0'
+ dependencies:
+ three: 0.155.0
+ dev: false
+
+ /troika-worker-utils@0.47.2:
+ resolution: {integrity: sha512-mzss4MeyzUkYBppn4x5cdAqrhBHFEuVmMMgLMTyFV23x6GvQMyo+/R5E5Lsbrt7WSt5RfvewjcwD1DChRTA9lA==}
+ dev: false
+
/ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
dev: true
@@ -2282,6 +2340,10 @@ packages:
vite: 4.4.4
dev: true
+ /webgl-sdf-generator@1.1.1:
+ resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==}
+ dev: false
+
/which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
diff --git a/src/lib/assets/vectors/github.glb b/src/lib/assets/vectors/github.glb
new file mode 100644
index 0000000..e297dce
Binary files /dev/null and b/src/lib/assets/vectors/github.glb differ
diff --git a/src/lib/assets/vectors/github.svg b/src/lib/assets/vectors/github.svg
new file mode 100644
index 0000000..37fa923
--- /dev/null
+++ b/src/lib/assets/vectors/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/lib/components/gltf/Github3d.svelte b/src/lib/components/gltf/Github3d.svelte
new file mode 100644
index 0000000..5e2c117
--- /dev/null
+++ b/src/lib/components/gltf/Github3d.svelte
@@ -0,0 +1,29 @@
+
+
+
+
+
+ {#await gltf}
+
+ {:then gltf}
+
+ {:catch error}
+
+ {/await}
+
+
+
diff --git a/src/lib/extrude-svg.ts b/src/lib/extrude-svg.ts
new file mode 100644
index 0000000..48b097c
--- /dev/null
+++ b/src/lib/extrude-svg.ts
@@ -0,0 +1,45 @@
+import type * as THREE from 'three';
+import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader';
+import type { SVGResult, SVGResultPaths } from 'three/examples/jsm/loaders/SVGLoader';
+
+import { Mesh } from 'three/src/objects/Mesh';
+import { Group } from 'three/src/objects/Group';
+import { MeshNormalMaterial } from 'three/src/materials/MeshNormalMaterial';
+import { ExtrudeGeometry } from 'three/src/geometries/ExtrudeGeometry';
+
+/**
+ * Parses the provided SVG markup and extrudes it into a 3D model using THREE.js.
+ * @param svgMarkup - SVG markup to extrude.
+ * @return Group containing all of the extruded SVG paths.
+ * @throws Error If the SVG markup is empty.
+ */
+export function extrudeSvg(svgMarkup: string): Group {
+ if (!svgMarkup) {
+ throw new Error('SVG markup is empty');
+ }
+
+ const svgData: SVGResult = new SVGLoader().parse(svgMarkup);
+ const material: MeshNormalMaterial = new MeshNormalMaterial();
+
+ const svgGroup: Mesh[][] = svgData.paths.map(createShapeFromPath);
+
+ const group = new Group();
+ svgGroup.flat().forEach(mesh => group.add(mesh));
+
+ return group;
+
+ function createShapeFromPath(path: SVGResultPaths): Mesh[] {
+ const shapes: THREE.Shape[] = path.toShapes(true);
+
+ return shapes.map(shape => extrudeShape(shape, material));
+ }
+
+ function extrudeShape(shape: THREE.Shape, material: MeshNormalMaterial): Mesh {
+ const geometry = new ExtrudeGeometry(shape, {
+ depth: 20,
+ bevelEnabled: false
+ });
+
+ return new Mesh(geometry, material);
+ }
+}
diff --git a/src/routes/tools/+page.svelte b/src/routes/tools/+page.svelte
index f62f863..f453a69 100644
--- a/src/routes/tools/+page.svelte
+++ b/src/routes/tools/+page.svelte
@@ -1,98 +1,7 @@
@@ -101,13 +10,9 @@
Tools
+
+
-
-
-
-
diff --git a/src/routes/tools/Scene.svelte b/src/routes/tools/Scene.svelte
new file mode 100644
index 0000000..1b985e3
--- /dev/null
+++ b/src/routes/tools/Scene.svelte
@@ -0,0 +1,42 @@
+
+
+ {
+ ref.lookAt(0, 1, 0);
+ }}
+/>
+
+ scale.set(1.5)}
+ on:pointerleave={() => scale.set(1)}
+ on:click={() => scale.set(3)}
+>
+
+
+
+
+ scale.set(1.5)}
+ on:pointerleave={() => scale.set(1)}
+ on:click={() => scale.set(3)}
+/>
diff --git a/static/github-transformed.glb b/static/github-transformed.glb
new file mode 100644
index 0000000..743764f
Binary files /dev/null and b/static/github-transformed.glb differ
diff --git a/vite.config.ts b/vite.config.ts
index bbf8c7d..cccd80e 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -2,5 +2,8 @@ import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
- plugins: [sveltekit()]
+ plugins: [sveltekit()],
+ ssr: {
+ noExternal: ['three']
+ }
});