75 lines
1.9 KiB
TypeScript
75 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { Mesh } from "three";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import * as THREE from "three";
|
|
import { useGLTF } from "@react-three/drei";
|
|
import { Canvas } from "@react-three/fiber";
|
|
|
|
type AngleEyeType = [number, number, number];
|
|
|
|
function SkeletonMesh() {
|
|
const [eyeAngle, setEyeAAngle] = useState<AngleEyeType>([
|
|
THREE.MathUtils.degToRad(0),
|
|
THREE.MathUtils.degToRad(0),
|
|
THREE.MathUtils.degToRad(0),
|
|
]);
|
|
const mesh = useRef<Mesh>(null!);
|
|
const skeleton = useRef<Mesh>(null!);
|
|
let head = useGLTF("/models/skeleton/head.gltf");
|
|
const eye = useGLTF("/models/skeleton/eye.gltf");
|
|
const eye2 = eye.scene.clone();
|
|
useEffect(() => {
|
|
window.addEventListener("mousemove", (event) => {
|
|
setEyeAAngle([
|
|
THREE.MathUtils.degToRad(
|
|
((event.clientY - window.innerHeight) * 15) / 360 + 30
|
|
),
|
|
THREE.MathUtils.degToRad(
|
|
((event.clientX - window.innerWidth) * 20 - 10) / 360 - 40
|
|
),
|
|
0,
|
|
]);
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<group>
|
|
<mesh
|
|
scale={0.25}
|
|
position={[0, -0.5, -5]}
|
|
rotation={[
|
|
THREE.MathUtils.degToRad(0),
|
|
THREE.MathUtils.degToRad(-35),
|
|
THREE.MathUtils.degToRad(0),
|
|
]}
|
|
ref={skeleton}
|
|
>
|
|
<primitive object={head.scene} />
|
|
</mesh>
|
|
<mesh ref={mesh} scale={0.2} position={[0, 0, -4]} rotation={eyeAngle}>
|
|
<primitive object={eye.scene} />
|
|
</mesh>
|
|
<mesh scale={0.2} position={[-1, 0, -5]} rotation={eyeAngle}>
|
|
<primitive object={eye2} />
|
|
</mesh>
|
|
</group>
|
|
);
|
|
}
|
|
|
|
export default function Skeleton() {
|
|
return (
|
|
<Canvas
|
|
className="h-100 w-100"
|
|
camera={{
|
|
type: "perspective",
|
|
position: [0, 0, 1],
|
|
rotation: [0, 0, 0],
|
|
}}
|
|
>
|
|
<pointLight intensity={15} />
|
|
<SkeletonMesh />
|
|
</Canvas>
|
|
);
|
|
}
|