feat(3d): add bocchi and react model

This commit is contained in:
xfy
2025-05-21 15:49:18 +08:00
parent fd5501e1d0
commit 36e380e424
6 changed files with 173 additions and 0 deletions

View File

@ -0,0 +1,112 @@
import { useGLTF, Float } from '@react-three/drei';
import { useLoader } from '@react-three/fiber';
import { JSX, useMemo } from 'react';
import { useMediaQuery } from 'react-responsive';
import * as THREE from 'three';
import { DRACOLoader, GLTF, GLTFLoader } from 'three-stdlib';
type GLTFResult = GLTF & {
nodes: {
Object_4: THREE.Mesh;
Object_6: THREE.Mesh;
Object_8: THREE.Mesh;
Object_10: THREE.Mesh;
Object_12: THREE.Mesh;
Object_14: THREE.Mesh;
Object_16: THREE.Mesh;
};
materials: {
main: THREE.MeshStandardMaterial;
material: THREE.MeshStandardMaterial;
yellow: THREE.MeshStandardMaterial;
blue: THREE.MeshStandardMaterial;
glass: THREE.MeshPhysicalMaterial;
};
};
const BocchiRubbishBin = (props: JSX.IntrinsicElements['group']) => {
const { nodes, materials } = useLoader(
GLTFLoader,
'/models/bocchi_the_rock-processed.glb',
(loader) => {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/libs/draco/');
loader.setDRACOLoader(dracoLoader);
},
) as unknown as GLTFResult;
const isMobile = useMediaQuery({ query: '(max-width: 768px)' });
const position = useMemo(() => {
if (isMobile) {
return [5, 3, 0] as const;
}
return [-12, 7, 0] as const;
}, [isMobile]);
return (
<Float floatIntensity={1.6}>
<group
{...props}
dispose={null}
position={position}
rotation={[Math.PI / 10, Math.PI / 10, 0]}
>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_4.geometry}
material={materials.main}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_6.geometry}
material={materials.material}
position={[0, 0.375, -0.099]}
rotation={[0.21, 0, 0]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_8.geometry}
material={materials.yellow}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_10.geometry}
material={materials.blue}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_12.geometry}
material={materials.main}
position={[0, 0.758, 0]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_14.geometry}
material={materials.glass}
position={[0.856, 0.277, 1.046]}
rotation={[-0.033, 0.088, 1.429]}
scale={[-0.175, 0.175, 0.175]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Object_16.geometry}
material={materials.glass}
position={[-0.852, 0.277, 1.046]}
rotation={[-0.032, -0.024, -1.413]}
scale={0.175}
/>
</group>
</Float>
);
};
useGLTF.preload('/models/bocchi_the_rock-processed.glb');
export default BocchiRubbishBin;

View File

@ -10,6 +10,8 @@ const ComputerModel = lazy(
() => import('components/models/home/computer-model'),
);
const Target = lazy(() => import('components/models/home/target'));
const ReactLogo = lazy(() => import('components/models/home/react-logo'));
const Bocchi = lazy(() => import('components/models/home/bocchi'));
const ComputerDesk = () => {
const isMobile = useMediaQuery({ query: '(max-width: 768px)' });
@ -32,7 +34,9 @@ const ComputerDesk = () => {
rotation={[0, -Math.PI, 0]}
/>
<Target />
<ReactLogo />
<PerspectiveCamera makeDefault position={[0, 0, 30]} />
<Bocchi />
</Suspense>
</Canvas>
{/* <Leva /> */}

View File

@ -0,0 +1,57 @@
import { useGLTF, Float } from '@react-three/drei';
import { useLoader } from '@react-three/fiber';
import { JSX, useMemo } from 'react';
import { useMediaQuery } from 'react-responsive';
import * as THREE from 'three';
import { DRACOLoader, GLTF, GLTFLoader } from 'three-stdlib';
type GLTFResult = GLTF & {
nodes: {
['React-Logo_Material002_0']: THREE.Mesh;
};
materials: {
['Material.002']: THREE.MeshStandardMaterial;
};
};
export function ReactLogo(props: JSX.IntrinsicElements['group']) {
const { nodes, materials } = useLoader(
GLTFLoader,
'/models/react_logo-processed.glb',
(loader) => {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/libs/draco/');
loader.setDRACOLoader(dracoLoader);
},
) as unknown as GLTFResult;
const isMobile = useMediaQuery({ query: '(max-width: 768px)' });
const position = useMemo(() => {
if (isMobile) {
return [5, 3, 0] as const;
}
return [10, 3, 0] as const;
}, [isMobile]);
return (
<Float floatIntensity={1.6}>
<group {...props} dispose={null}>
<group scale={0.3} position={position}>
<mesh
castShadow
receiveShadow
geometry={nodes['React-Logo_Material002_0'].geometry}
material={materials['Material.002']}
position={[0, 7.935, 18.102]}
rotation={[0, 0, -Math.PI / 2]}
scale={[0.39, 0.39, 0.5]}
/>
</group>
</group>
</Float>
);
}
useGLTF.preload('/models/react_logo.glb');
export default ReactLogo;