feat: add home page model

This commit is contained in:
xfy
2025-05-21 13:49:31 +08:00
parent d05a01ea9e
commit 3ac7d42cc1
8 changed files with 269 additions and 1 deletions

View File

@ -3,7 +3,9 @@ import dynamic from 'next/dynamic';
import Image from 'next/image'; import Image from 'next/image';
import styles from 'styles/index/index.module.css'; import styles from 'styles/index/index.module.css';
const HomeModel = dynamic(() => import('components/models/home-model')); const ComputerDesk = dynamic(
() => import('components/models/home/computer-desk'),
);
export const metadata = { export const metadata = {
title: 'RUA - Home', title: 'RUA - Home',
@ -12,6 +14,10 @@ export const metadata = {
export default function Page() { export default function Page() {
return ( return (
<main className="flex items-stretch justify-center flex-1 text-xl"> <main className="flex items-stretch justify-center flex-1 text-xl">
<div className={clsx('top-0 left-0 right-0 bottom-0 absolute')}>
<ComputerDesk />
</div>
<div className="text-6xl flex items-center"> <div className="text-6xl flex items-center">
<span <span
className={clsx( className={clsx(

View File

@ -0,0 +1,78 @@
'use client';
import { Canvas } from '@react-three/fiber';
import { lazy, Suspense } from 'react';
import Loading from './loading';
import { PerspectiveCamera } from '@react-three/drei/core/PerspectiveCamera';
import { Leva, useControls } from 'leva';
const ComputerModel = lazy(
() => import('components/models/home/computer-model'),
);
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,
},
});
return (
<>
<Canvas>
<Suspense fallback={<Loading />}>
<ambientLight intensity={1} />
<directionalLight position={[10, 10, 10]} intensity={0.5} />
<ComputerModel
scale={0.1}
position={[0.6, -6.0, 0]}
rotation={[0, -Math.PI, 0]}
/>
<PerspectiveCamera makeDefault position={[0, 0, 30]} />
</Suspense>
</Canvas>
<Leva />
</>
);
};
export default ComputerDesk;

View File

@ -0,0 +1,154 @@
'use client';
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Author: david.campuzano (https://sketchfab.com/david.campuzano)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/hacker-room-stylized-a0cfe6edf2dd494c8a95addf6bb13a10
Title: Hacker Room - Stylized
*/
import { useGLTF } from '@react-three/drei';
import { useLoader } from '@react-three/fiber';
import { JSX } from 'react';
import * as THREE from 'three';
import { DRACOLoader, GLTF, GLTFLoader } from 'three-stdlib';
type GLTFResult = GLTF & {
nodes: {
computer_computer_mat_0: THREE.Mesh;
server_server_mat_0: THREE.Mesh;
vhs_vhsPlayer_mat_0: THREE.Mesh;
shelf_stand_mat_0: THREE.Mesh;
keyboard_mat_mat_mat_0: THREE.Mesh;
arm_arm_mat_0: THREE.Mesh;
Tv_tv_mat_0: THREE.Mesh;
table_table_mat_0: THREE.Mesh;
Cables_cables_mat_0: THREE.Mesh;
props_props_mat_0: THREE.Mesh;
screen_screens_0: THREE.Mesh;
screen_glass_glass_0: THREE.Mesh;
Ground_ground_mat_0: THREE.Mesh;
peripherals_key_mat_0: THREE.Mesh;
};
materials: {
computer_mat: THREE.MeshStandardMaterial;
server_mat: THREE.MeshStandardMaterial;
vhsPlayer_mat: THREE.MeshStandardMaterial;
stand_mat: THREE.MeshStandardMaterial;
mat_mat: THREE.MeshStandardMaterial;
arm_mat: THREE.MeshStandardMaterial;
tv_mat: THREE.MeshStandardMaterial;
table_mat: THREE.MeshStandardMaterial;
cables_mat: THREE.MeshStandardMaterial;
props_mat: THREE.MeshStandardMaterial;
screens: THREE.MeshStandardMaterial;
glass: THREE.MeshPhysicalMaterial;
ground_mat: THREE.MeshStandardMaterial;
key_mat: THREE.MeshStandardMaterial;
};
};
export function Model(props: JSX.IntrinsicElements['group']) {
const { nodes, materials } = useLoader(
GLTFLoader,
'/models/hacker-room/hacker_room_-_stylized-processed.glb',
(loader) => {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/libs/draco/');
loader.setDRACOLoader(dracoLoader);
},
) as unknown as GLTFResult;
return (
<group {...props} dispose={null}>
<mesh
castShadow
receiveShadow
geometry={nodes.computer_computer_mat_0.geometry}
material={materials.computer_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.server_server_mat_0.geometry}
material={materials.server_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.vhs_vhsPlayer_mat_0.geometry}
material={materials.vhsPlayer_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.shelf_stand_mat_0.geometry}
material={materials.stand_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.keyboard_mat_mat_mat_0.geometry}
material={materials.mat_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.arm_arm_mat_0.geometry}
material={materials.arm_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Tv_tv_mat_0.geometry}
material={materials.tv_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.table_table_mat_0.geometry}
material={materials.table_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Cables_cables_mat_0.geometry}
material={materials.cables_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.props_props_mat_0.geometry}
material={materials.props_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.screen_screens_0.geometry}
material={materials.screens}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.screen_glass_glass_0.geometry}
material={materials.glass}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Ground_ground_mat_0.geometry}
material={materials.ground_mat}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.peripherals_key_mat_0.geometry}
material={materials.key_mat}
/>
</group>
);
}
useGLTF.preload('/models/hacker-room/hacker_room_-_stylized-processed.glb');
export default Model;

View File

@ -0,0 +1,26 @@
import { Html, useProgress } from '@react-three/drei';
import clsx from 'clsx';
import RUALoading from 'components/rua/loading/rua-loading';
const Loading = () => {
const { progress } = useProgress();
console.log(progress);
return (
<Html as="div">
<div
className={clsx(
'h-full w-full absolute',
'top-0 left-0 flex',
'justify-center items-center',
'bg-bluish-gray dark:bg-rua-gray-900',
'transition-all duration-300',
)}
>
<RUALoading />
</div>
</Html>
);
};
export default Loading;

View File

@ -45,6 +45,7 @@
"remark-rehype": "^11.1.1", "remark-rehype": "^11.1.1",
"sharp": "^0.34.1", "sharp": "^0.34.1",
"three": "^0.176.0", "three": "^0.176.0",
"three-stdlib": "^2.36.0",
"unified": "^11.0.5", "unified": "^11.0.5",
"zustand": "^5.0.4" "zustand": "^5.0.4"
}, },

3
pnpm-lock.yaml generated
View File

@ -98,6 +98,9 @@ importers:
three: three:
specifier: ^0.176.0 specifier: ^0.176.0
version: 0.176.0 version: 0.176.0
three-stdlib:
specifier: ^2.36.0
version: 2.36.0(three@0.176.0)
unified: unified:
specifier: ^11.0.5 specifier: ^11.0.5
version: 11.0.5 version: 11.0.5

Binary file not shown.