diff --git a/README.md b/README.md index 2bc2568..6773ea8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ SvelteKit TypeScript Tailwind CSS - Three.js Bun @@ -22,7 +21,7 @@ The site recreates my [blomarchy](https://git.sirblob.co/SirBlob/blomarchy) setu - **Kitty terminals** - a real command line with history and tab completion. Try `fastfetch`, `whoami` or `cowsay`. - **Desktop icons** - grouped into pages, terminal scripts and socials (GitHub, LinkedIn, Devpost, Discord). - **13 themes** - Flats, Retro 82, Tokyo Night, Catppuccin, Arch Linux, Gruvbox, Nord, Kanagawa, Wintry, Rose, Cerberus, Catppuccin Latte and Rose Pine Dawn, each with its own wallpaper. -- **Portfolio** - about, portfolio, projects (open source, packages, hackathons, research), blog with RSS, 3D models and links with QR codes. +- **Portfolio** - about, portfolio, projects (open source, packages, hackathons, research), blog with RSS and links with QR codes. - **Mobile friendly** - on small screens windows go fullscreen with tabs to switch between them. ## Keybinds diff --git a/content/desktop.json b/content/desktop.json index 85061f4..20e8276 100644 --- a/content/desktop.json +++ b/content/desktop.json @@ -6,8 +6,7 @@ { "number": 3, "name": "projects", "path": "/projects" }, { "number": 4, "name": "blog", "path": "/blog" }, { "number": 5, "name": "links", "path": "/links" }, - { "number": 6, "name": "portfolio", "path": "/portfolio" }, - { "number": 7, "name": "models", "path": "/models" } + { "number": 6, "name": "portfolio", "path": "/portfolio" } ], "iconGroups": [ { @@ -18,7 +17,6 @@ { "label": "projects", "icon": "ph:folder-open-duotone", "open": { "page": "/projects" } }, { "label": "hackathons", "icon": "ph:trophy-duotone", "open": { "page": "/projects/hackathons" } }, { "label": "blog", "icon": "ph:notebook-duotone", "open": { "page": "/blog" } }, - { "label": "models", "icon": "ph:cube-duotone", "open": { "page": "/models" } }, { "label": "links", "icon": "ph:qr-code-duotone", "open": { "page": "/links" } } ] }, diff --git a/content/models.json b/content/models.json deleted file mode 100644 index 1c764d6..0000000 --- a/content/models.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "name": "Bake Potato", - "description": "A fun baked-potato 3D model for demos and testing.", - "file": "/models/BakePotato.glb", - "software": ["Blender"], - "polyCount": "1k tris" - }, - { - "name": "Soda Can", - "description": "A realistic soda can GLB used for materials/tests.", - "file": "/models/Soda.glb", - "software": ["Blender"], - "polyCount": "800 tris" - } -] diff --git a/package.json b/package.json index 6bbc75d..74eda80 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,8 @@ }, "dependencies": { "@iconify/svelte": "^5.2.3", - "@types/three": "^0.185.4", "discord.js": "^14.27.0", - "svelte-qrcode": "^1.0.1", - "three": "^0.185.1" + "svelte-qrcode": "^1.0.1" }, "imports": { "#lib": "./src/lib/index.js", diff --git a/src/lib/components/models/ModelViewer.svelte b/src/lib/components/models/ModelViewer.svelte deleted file mode 100644 index 1cc2a4a..0000000 --- a/src/lib/components/models/ModelViewer.svelte +++ /dev/null @@ -1,156 +0,0 @@ - - -
-
- {modelName} -
- - - - - -
-
-
- {#if status !== 'ready'} -
- {#if status === 'loading'} - loading model... - {:else if status === 'error'} - failed to load model - {:else} - WebGL is not available in this browser - {/if} -
- {/if} -
-
drag to rotate · scroll to zoom · arrow keys after clicking
-
- - diff --git a/src/lib/content/index.ts b/src/lib/content/index.ts index 9d18042..0806452 100644 --- a/src/lib/content/index.ts +++ b/src/lib/content/index.ts @@ -2,7 +2,6 @@ import profileData from '#content/profile.json'; import experienceData from '#content/experience.json'; import leadershipData from '#content/leadership.json'; import aboutData from '#content/about.json'; -import modelsData from '#content/models.json'; import desktopData from '#content/desktop.json'; import blogData from '#content/blog.json'; import openSourceData from '#content/projects/opensource.json'; @@ -15,7 +14,6 @@ import type { DesktopContent, Experience, Leadership, - Model3D, Profile, Project, ProjectCategory, @@ -28,7 +26,6 @@ export const profile: Profile = profileData; export const experience: Experience[] = experienceData; export const leadership: Leadership[] = leadershipData; export const about: AboutContent = aboutData; -export const models: Model3D[] = modelsData; export const desktop: DesktopContent = desktopData; export const blogSettings: BlogSettings = blogData; diff --git a/src/lib/content/types.ts b/src/lib/content/types.ts index 9b86ad2..10119f8 100644 --- a/src/lib/content/types.ts +++ b/src/lib/content/types.ts @@ -119,14 +119,6 @@ export interface AboutContent { movies: RatedTitle[]; } -export interface Model3D { - name: string; - description: string; - file: string; - software: string[]; - polyCount?: string; -} - export type DesktopAction = { page: string } | { terminal: string } | { url: string }; export interface DesktopIconGroup { diff --git a/src/lib/models/model-scene.ts b/src/lib/models/model-scene.ts deleted file mode 100644 index b7f99b4..0000000 --- a/src/lib/models/model-scene.ts +++ /dev/null @@ -1,132 +0,0 @@ -import * as THREE from 'three'; -import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; -import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - -const modelSize = 1.5; -const startingCameraPosition = new THREE.Vector3(0, 0.6, 2.5); - -export class ModelScene { - private scene = new THREE.Scene(); - private camera: THREE.PerspectiveCamera; - private renderer: THREE.WebGLRenderer; - private controls: OrbitControls; - private ambientLight = new THREE.AmbientLight(0xffffff, 0.6); - private model: THREE.Object3D | null = null; - private animationFrame = 0; - - constructor(private container: HTMLElement) { - const { clientWidth, clientHeight } = container; - this.camera = new THREE.PerspectiveCamera(45, clientWidth / clientHeight, 0.1, 1000); - this.camera.position.copy(startingCameraPosition); - - this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); - this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); - this.renderer.setSize(clientWidth, clientHeight); - this.renderer.outputColorSpace = THREE.SRGBColorSpace; - this.renderer.toneMapping = THREE.ACESFilmicToneMapping; - container.appendChild(this.renderer.domElement); - - this.controls = new OrbitControls(this.camera, this.renderer.domElement); - this.controls.enableDamping = true; - this.controls.enablePan = false; - this.controls.minDistance = 1; - this.controls.maxDistance = 10; - this.controls.autoRotateSpeed = 2; - this.controls.listenToKeyEvents(container); - - this.addLights(); - this.animate(); - } - - private addLights() { - const keyLight = new THREE.DirectionalLight(0xffffff, 1); - keyLight.position.set(5, 5, 5); - const fillLight = new THREE.DirectionalLight(0xffffff, 0.5); - fillLight.position.set(-5, 3, -5); - const rimLight = new THREE.DirectionalLight(0x88ccff, 0.3); - rimLight.position.set(0, -3, -5); - this.scene.add(this.ambientLight, keyLight, fillLight, rimLight); - } - - private animate = () => { - this.animationFrame = requestAnimationFrame(this.animate); - this.controls.update(); - this.renderer.render(this.scene, this.camera); - }; - - load(url: string): Promise { - return new Promise((resolve, reject) => { - new GLTFLoader().load( - url, - (gltf) => { - this.removeModel(); - const model = gltf.scene; - const bounds = new THREE.Box3().setFromObject(model); - const center = bounds.getCenter(new THREE.Vector3()); - const largestSide = Math.max(...bounds.getSize(new THREE.Vector3()).toArray()); - const scale = modelSize / largestSide; - model.scale.setScalar(scale); - model.position.sub(center.multiplyScalar(scale)); - this.scene.add(model); - this.model = model; - this.resetCamera(); - resolve(); - }, - undefined, - reject - ); - }); - } - - private removeModel() { - if (!this.model) return; - this.scene.remove(this.model); - this.model.traverse((child) => { - if (!(child instanceof THREE.Mesh)) return; - child.geometry.dispose(); - const materials = Array.isArray(child.material) ? child.material : [child.material]; - materials.forEach((material) => material.dispose()); - }); - this.model = null; - } - - setAutoRotate(enabled: boolean) { - this.controls.autoRotate = enabled; - } - - setWireframe(enabled: boolean) { - this.model?.traverse((child) => { - if (!(child instanceof THREE.Mesh)) return; - const materials = Array.isArray(child.material) ? child.material : [child.material]; - materials.forEach((material) => { - if ('wireframe' in material) material.wireframe = enabled; - }); - }); - } - - setBrightness(intensity: number) { - this.ambientLight.intensity = intensity; - } - - resetCamera() { - this.camera.position.copy(startingCameraPosition); - this.controls.target.set(0, 0, 0); - this.controls.update(); - } - - resize() { - const { clientWidth, clientHeight } = this.container; - if (!clientWidth || !clientHeight) return; - this.camera.aspect = clientWidth / clientHeight; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(clientWidth, clientHeight); - } - - dispose() { - cancelAnimationFrame(this.animationFrame); - this.removeModel(); - this.controls.dispose(); - this.renderer.dispose(); - this.renderer.domElement.remove(); - } -} diff --git a/src/lib/site/pages.ts b/src/lib/site/pages.ts index 6eb9986..56fd2c5 100644 --- a/src/lib/site/pages.ts +++ b/src/lib/site/pages.ts @@ -27,7 +27,6 @@ export const sitePages: SitePage[] = [ })) }, { name: 'blog', path: '/blog', title: 'Blog', description: 'Notes and write-ups from my projects.', icon: 'ph:notebook-duotone' }, - { name: 'models', path: '/models', title: '3D Models', description: 'A collection of 3D models with an interactive viewer.', icon: 'ph:cube-duotone' }, { name: 'links', path: '/links', title: 'Links', description: 'All my links with scannable QR codes.', icon: 'ph:qr-code-duotone' } ]; diff --git a/src/routes/models/+page.svelte b/src/routes/models/+page.svelte deleted file mode 100644 index cbfb162..0000000 --- a/src/routes/models/+page.svelte +++ /dev/null @@ -1,89 +0,0 @@ - - -
- - -
- {#each models as model (model.file)} - - {/each} -
- - {#if selectedModel} - - -
-

{selectedModel.description}

-
- {#each selectedModel.software as software, index (software)} - - {/each} - {#if selectedModel.polyCount} - {selectedModel.polyCount} - {/if} - download .glb -
-
- {/if} - -

{models.length} models available

-
- - diff --git a/static/models/BakePotato.glb b/static/models/BakePotato.glb deleted file mode 100644 index d1953b4..0000000 Binary files a/static/models/BakePotato.glb and /dev/null differ diff --git a/static/models/Soda.glb b/static/models/Soda.glb deleted file mode 100644 index d4aba06..0000000 Binary files a/static/models/Soda.glb and /dev/null differ