import * as THREE from 'three' import React, { useState, useEffect, useRef } from 'react'; import { OrbitControls } from '@react-three/drei' import { useFrame, Canvas } from '@react-three/fiber'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { VRM, VRMUtils, VRMLoaderPlugin } from '@pixiv/three-vrm'; import { VRMAnimationLoaderPlugin, VRMAnimation, createVRMAnimationClip } from "@pixiv/three-vrm-animation"; interface ModelProps { url: string url_anim: string scale: [number, number, number] position: [number, number, number] rotation: [number, number, number] } const VRMModel: React.FC = ({ url, url_anim, position, rotation, scale }) => { const [vrm, setVrm] = useState(null); const mixerRef = useRef(null); useEffect(() => { const loader = new GLTFLoader(); loader.register((parser) => new VRMLoaderPlugin(parser)); loader.register((parser) => new VRMAnimationLoaderPlugin(parser)); loader.load(url, (gltf) => { const vrmModel = gltf.userData.vrm as VRM; VRMUtils.removeUnnecessaryJoints(vrmModel.scene); setVrm(vrmModel); const mixer = new THREE.AnimationMixer(vrmModel.scene); mixerRef.current = mixer; loader.load(url_anim, (animGltf) => { const vrmAnimations = animGltf.userData.vrmAnimations as VRMAnimation[]; if (vrmAnimations && vrmAnimations.length > 0) { const clip = createVRMAnimationClip(vrmAnimations[0], vrmModel); mixer.clipAction(clip).play(); } }); }); }, [url, url_anim]); useFrame((state, delta) => { if (mixerRef.current) mixerRef.current.update(delta); if (vrm) vrm.update(delta); }); return vrm ? : null; }; export const VRMModelCanvas = () => { return (
{/* Light gray background */}
) } export default VRMModelCanvas;