Model.tsx (2942B)
1 // Model.tsx 2 import { FC, useState, useEffect } from "react" 3 import { Html} from "@react-three/drei" 4 import { GLTFLoader, GLTF } from "three/examples/jsm/loaders/GLTFLoader" 5 import { VRMLoaderPlugin } from "@pixiv/three-vrm" 6 import { VRMAnimationLoaderPlugin } from "@pixiv/three-vrm-animation" 7 8 9 10 const Model: FC = () => { 11 const [gltf, setGltf] = useState<GLTF>() 12 const [progress, setProgress] = useState<number>(0) 13 14 useEffect(() => { 15 if (!gltf) { 16 const loader = new GLTFLoader() 17 loader.register((parser) => { 18 return new VRMLoaderPlugin(parser) 19 }); 20 loader.register((parser) => { 21 return new VRMAnimationLoaderPlugin(parser) 22 }); 23 24 loader.load( 25 "/models/Setok.vrm", 26 (tmpGltf) => { 27 setGltf(tmpGltf) 28 console.log("loaded") 29 }, 30 // called as loading progresses 31 (xhr) => { 32 setProgress((xhr.loaded / xhr.total) * 100) 33 console.log((xhr.loaded / xhr.total) * 100 + "% loaded") 34 }, 35 // called when loading has errors 36 (error) => { 37 console.log("An error happened") 38 console.log(error) 39 } 40 ) 41 let currentVrm: any = undefined; 42 let currentVrmAnimation: any = undefined; 43 let currentMixer:any = undefined; 44 function load(url: string) { 45 loader.load( 46 url, 47 // ロード時に呼ばれる 48 (gltf) => { 49 tryInitVRM(gltf); 50 tryInitVRMA(gltf); 51 }, 52 // プログレス時に呼ばれる 53 (progress) => console.log( 54 "Loading model...", 55 100.0 * (progress.loaded / progress.total), "%" 56 ), 57 // エラー時に呼ばれる 58 (error) => console.error(error) 59 ); 60 } 61 function tryInitVRM(gltf: any) { 62 const vrm = gltf.userData.vrm; 63 if ( vrm == null ) { 64 return; 65 } 66 currentVrm = vrm; 67 scene.add(vrm.scene); 68 initAnimationClip(); 69 } 70 71 // VRMAの読み込み 72 function tryInitVRMA(gltf: any) { 73 const vrmAnimations = gltf.userData.vrmAnimations; 74 if (vrmAnimations == null) { 75 return; 76 } 77 currentVrmAnimation = vrmAnimations[0] ?? null; 78 initAnimationClip(); 79 } 80 function initAnimationClip() { 81 if (currentVrm && currentVrmAnimation) { 82 currentMixer = new THREE.AnimationMixer(currentVrm.scene); 83 const clip = createVRMAnimationClip(currentVrmAnimation, currentVrm); 84 currentMixer.clipAction(clip).play(); 85 } 86 } 87 // https://note.com/npaka/n/nf632f283f89a 88 load("/animations/VRMA_01.vrma") 89 } 90 }, [gltf]) 91 92 return ( 93 <> 94 {gltf ? ( 95 <primitive object={gltf.scene} /> 96 ) : ( 97 <Html center>{progress} % loaded</Html> 98 )} 99 </> 100 ) 101 } 102 103 export default Model