diff --git a/app/page.tsx b/app/page.tsx index 72d67c4..dd42757 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -18,23 +18,24 @@ export default function Page() { -
- +

- Hello World! - - - hands - + Hello World +

+

+ TECH OTAKUS SAVE THE WORLD +

); diff --git a/components/models/home/computer-desk.tsx b/components/models/home/computer-desk.tsx index f0b6430..d73d9f3 100644 --- a/components/models/home/computer-desk.tsx +++ b/components/models/home/computer-desk.tsx @@ -1,60 +1,24 @@ 'use client'; import { Canvas } from '@react-three/fiber'; -import { lazy, Suspense } from 'react'; +import { lazy, Suspense, useMemo } from 'react'; import Loading from './loading'; import { PerspectiveCamera } from '@react-three/drei/core/PerspectiveCamera'; -import { Leva, useControls } from 'leva'; +import { useMediaQuery } from 'react-responsive'; const ComputerModel = lazy( () => import('components/models/home/computer-model'), ); +const Target = lazy(() => import('components/models/home/target')); const ComputerDesk = () => { - const c = useControls('RUARoom', { - positionX: { - value: 0, - min: -10, - max: 10, - step: 0.1, - }, - positionY: { - value: 0, - min: -10, - max: 10, - step: 0.1, - }, - positionZ: { - value: 0, - min: -10, - max: 10, - step: 0.01, - }, - rotationX: { - value: 0, - min: -Math.PI, - max: Math.PI, - step: 0.01, - }, - rotationY: { - value: 0, - min: -Math.PI, - max: Math.PI, - step: 0.01, - }, - rotationZ: { - value: 0, - min: -Math.PI, - max: Math.PI, - step: 0.001, - }, - scale: { - value: 1, - min: 0.1, - max: 10, - step: 0.01, - }, - }); + const isMobile = useMediaQuery({ query: '(max-width: 768px)' }); + const scale = useMemo(() => { + if (isMobile) { + return 0.08; + } + return 0.1; + }, [isMobile]); return ( <> @@ -63,14 +27,15 @@ const ComputerDesk = () => { + - + {/* */} ); }; diff --git a/components/models/home/target.tsx b/components/models/home/target.tsx new file mode 100644 index 0000000..69089e6 --- /dev/null +++ b/components/models/home/target.tsx @@ -0,0 +1,89 @@ +/** + * Samll target item in home page + */ +import * as THREE from 'three'; +import React, { JSX, useMemo, useRef } from 'react'; +import { useGLTF } from '@react-three/drei'; +import { DRACOLoader, GLTF, GLTFLoader } from 'three-stdlib'; +import { useLoader } from '@react-three/fiber'; +import gsap from 'gsap'; +import { useGSAP } from '@gsap/react'; +import { useMediaQuery } from 'react-responsive'; + +type GLTFResult = GLTF & { + nodes: { + Cylinder016: THREE.Mesh; + Cylinder016_1: THREE.Mesh; + Cylinder016_2: THREE.Mesh; + }; + materials: { + ['Red.025']: THREE.MeshStandardMaterial; + ['White.025']: THREE.MeshStandardMaterial; + ['BrownDark.018']: THREE.MeshStandardMaterial; + }; +}; + +export function Target(props: JSX.IntrinsicElements['group']) { + const { nodes, materials } = useLoader( + GLTFLoader, + '/models/target-processed.gltf', + (loader) => { + const dracoLoader = new DRACOLoader(); + dracoLoader.setDecoderPath('/libs/draco/'); + loader.setDRACOLoader(dracoLoader); + }, + ) as unknown as GLTFResult; + + // animation + const targetRef = useRef(null); + useGSAP(() => { + if (!targetRef.current) return; + gsap.to(targetRef.current.position, { + y: targetRef.current.position.y + 0.5, + duration: 1.5, + repeat: -1, + yoyo: true, + }); + }); + + const isMobile = useMediaQuery({ query: '(max-width: 768px)' }); + const position = useMemo<[number, number, number]>(() => { + if (isMobile) { + return [-5, -5, 3] as const; + } + return [-14, -8, 0] as const; + }, [isMobile]); + + return ( + + + + + + + + ); +} + +useGLTF.preload('/models/target-processed.gltf'); + +export default Target; diff --git a/package.json b/package.json index 7a3bbc6..7605f23 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@docsearch/css": "^3.9.0", "@docsearch/react": "^3.9.0", "@giscus/react": "^3.1.0", + "@gsap/react": "^2.1.2", "@octokit/core": "^6.1.5", "@octokit/plugin-rest-endpoint-methods": "^14.0.0", "@react-spring/three": "^10.0.0", @@ -30,12 +31,14 @@ "@tailwindcss/postcss": "^4.1.7", "algoliasearch": "^5.25.0", "dayjs": "^1.11.13", + "gsap": "^3.13.0", "next": "15.3.2", "next-mdx-remote": "^5.0.0", "next-themes": "^0.4.6", "react": "^19.1.0", "react-dom": "^19.1.0", "react-icons": "^5.5.0", + "react-responsive": "^10.0.1", "rehype-highlight": "^7.0.0", "rehype-react": "^8.0.0", "rehype-slug": "^6.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a05c020..dea5bcb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@giscus/react': specifier: ^3.1.0 version: 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@gsap/react': + specifier: ^2.1.2 + version: 2.1.2(gsap@3.13.0)(react@19.1.0) '@octokit/core': specifier: ^6.1.5 version: 6.1.5 @@ -53,6 +56,9 @@ importers: dayjs: specifier: ^1.11.13 version: 1.11.13 + gsap: + specifier: ^3.13.0 + version: 3.13.0 next: specifier: 15.3.2 version: 15.3.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.0) @@ -71,6 +77,9 @@ importers: react-icons: specifier: ^5.5.0 version: 5.5.0(react@19.1.0) + react-responsive: + specifier: ^10.0.1 + version: 10.0.1(react@19.1.0) rehype-highlight: specifier: ^7.0.0 version: 7.0.1 @@ -449,6 +458,12 @@ packages: react: ^16 || ^17 || ^18 || ^19 react-dom: ^16 || ^17 || ^18 || ^19 + '@gsap/react@2.1.2': + resolution: {integrity: sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==} + peerDependencies: + gsap: ^3.12.5 + react: '>=17' + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -1608,6 +1623,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-mediaquery@0.1.2: + resolution: {integrity: sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -2133,6 +2151,9 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} + gsap@3.13.0: + resolution: {integrity: sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==} + gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} @@ -2198,6 +2219,9 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2608,6 +2632,9 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + matchmediaquery@0.4.2: + resolution: {integrity: sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==} + mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} @@ -3072,6 +3099,12 @@ packages: peerDependencies: react: ^19.0.0 + react-responsive@10.0.1: + resolution: {integrity: sha512-OM5/cRvbtUWEX8le8RCT8scA8y2OPtb0Q/IViEyCEM5FBN8lRrkUOZnu87I88A6njxDldvxG+rLBxWiA7/UM9g==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8.0' + react-use-measure@2.1.7: resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==} peerDependencies: @@ -3238,6 +3271,9 @@ packages: resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} engines: {node: '>=0.10.0'} + shallow-equal@3.1.0: + resolution: {integrity: sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==} + sharp@0.34.1: resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4116,6 +4152,11 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) + '@gsap/react@2.1.2(gsap@3.13.0)(react@19.1.0)': + dependencies: + gsap: 3.13.0 + react: 19.1.0 + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -5323,6 +5364,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-mediaquery@0.1.2: {} + csstype@3.1.3: {} d@1.0.2: @@ -6021,6 +6064,8 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 + gsap@3.13.0: {} + gzip-size@6.0.0: dependencies: duplexer: 0.1.2 @@ -6117,6 +6162,8 @@ snapshots: html-escaper@2.0.2: {} + hyphenate-style-name@1.1.0: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -6492,6 +6539,10 @@ snapshots: markdown-table@3.0.4: {} + matchmediaquery@0.4.2: + dependencies: + css-mediaquery: 0.1.2 + mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.4 @@ -7237,6 +7288,14 @@ snapshots: react: 19.1.0 scheduler: 0.25.0 + react-responsive@10.0.1(react@19.1.0): + dependencies: + hyphenate-style-name: 1.1.0 + matchmediaquery: 0.4.2 + prop-types: 15.8.1 + react: 19.1.0 + shallow-equal: 3.1.0 + react-use-measure@2.1.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 @@ -7481,6 +7540,8 @@ snapshots: is-plain-object: 2.0.4 split-string: 3.1.0 + shallow-equal@3.1.0: {} + sharp@0.34.1: dependencies: color: 4.2.3 diff --git a/public/models/lowpoly-desk/lowpoly_desk-processed.glb b/public/models/lowpoly-desk/lowpoly_desk-processed.glb deleted file mode 100644 index ac178c8..0000000 Binary files a/public/models/lowpoly-desk/lowpoly_desk-processed.glb and /dev/null differ diff --git a/public/models/target-processed.gltf b/public/models/target-processed.gltf new file mode 100644 index 0000000..12f635d --- /dev/null +++ b/public/models/target-processed.gltf @@ -0,0 +1,288 @@ +{ + "asset": { + "generator": "Khronos glTF Blender I/O v1.5.17", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "name": "Scene", + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "mesh": 0, + "name": "targetStand", + "rotation": [ + 0.7071068286895752, + 0, + 0, + 0.7071067094802856 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + } + ], + "materials": [ + { + "doubleSided": true, + "name": "Red.025", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1, + 0.02505292184650898, + 0.11802464723587036, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 0.20000000298023224 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE" + }, + { + "doubleSided": true, + "name": "White.025", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.799102783203125, + 0.799102783203125, + 0.799102783203125, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE" + }, + { + "doubleSided": true, + "name": "BrownDark.018", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.32694560289382935, + 0.10152623057365417, + 0.05927089974284172, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 0.4000000059604645 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE" + } + ], + "meshes": [ + { + "name": "Cylinder.016", + "primitives": [ + { + "attributes": { + "POSITION": 1, + "NORMAL": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "material": 0, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 0, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + } + } + } + }, + { + "attributes": { + "POSITION": 5, + "NORMAL": 6, + "TEXCOORD_0": 7 + }, + "indices": 4, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 1, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + } + } + } + }, + { + "attributes": { + "POSITION": 9, + "NORMAL": 10, + "TEXCOORD_0": 11 + }, + "indices": 8, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 2, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + } + } + } + } + ] + } + ], + "accessors": [ + { + "componentType": 5123, + "count": 282, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 96, + "max": [ + 0.5114296778097465, + 0.8281944695337842, + -0.7671326534539592 + ], + "min": [ + -0.5114295586004569, + 0.43332787314507226, + -1.7111184104338004 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 96, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 96, + "type": "VEC2" + }, + { + "componentType": 5123, + "count": 1818, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 734, + "max": [ + 0.684837244316375, + 0.8791963504067735, + -0.4541223597165487 + ], + "min": [ + -0.6851508665445902, + -0.0215896416071513, + -1.85557300332819 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 734, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 734, + "type": "VEC2" + }, + { + "componentType": 5123, + "count": 252, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 120, + "max": [ + 0.6735454190924626, + 0.6617427920794337, + 0.0007889245740948514 + ], + "min": [ + -0.6735453594878178, + -0.6570781458571415, + -1.3108001936629277 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 120, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 120, + "type": "VEC2" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 729 + }, + { + "buffer": 0, + "byteOffset": 736, + "byteLength": 2912 + }, + { + "buffer": 0, + "byteOffset": 3648, + "byteLength": 758 + } + ], + "buffers": [ + { + "name": "target-processed", + "byteLength": 4408, + "uri": "data:application/octet-stream;base64,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" + } + ], + "extensionsRequired": [ + "KHR_draco_mesh_compression" + ], + "extensionsUsed": [ + "KHR_draco_mesh_compression" + ] +}