💬
React+TypeScript+R3Fのtutorial応用編3(glTFで3Dアニメーション(単一モデル))
Abstract
今回の参考はここ(R3F Animation Mixer)。このソースをTypeScriptで実装しなおす。
といってもほとんどそのままで動いた。
必要最小で構成されてて、ホント感激!! 分かりやすい。
ポイント
- *.glbの3Dモデル読込みと表示
- *.glbのアニメーションデータ読込みと実行
結論
今回のソースコードはココ↓
前提
- React+Typescriptの開発環境は構築済 [環境構築]WindowsにVSCode+React+TypeScriptの開発環境を構築してみた。
- このスケルトンコードから始める。react-r3f-base-onebox
手順
1.プロジェクト生成 -> VSCodeで開く
めんどいから、このスケルトンコードから始める。react-r3f-base-onebox
で、下記コマンドでフォルダ名とか整備する。
フォルダリネームとか
$ D:
$ cd .\Products\React.js\ # ご自身の適当なフォルダで。
$ rd /q /s D:\Products\React.js\react-r3f-advanced003
$ git clone https://github.com/aaaa1597/react-r3f-base-onebox.git
$ rd /q /s react-r3f-base-onebox/.git
$ ren react-r3f-base-onebox react-r3f-advanced003
$ cd react-r3f-advanced003
準備
コマンドプロンプト
$ npm install --save three
$ npm install --save @types/three
$ npm install --save @react-three/fiber
$ npm install --save @react-three/drei
準備2
- ここからDLしたanimate-bones.glb をプロジェクトの"react-r3f-advanced003/public/"配下にコピー。
.eslintrc.jsを修正
エラーになるので、ignoreに追加
.eslintrc.js
"rules": {
- "react/no-unknown-property": ['error', { ignore: ['css', "args", 'wireframe', 'rotation-x', 'rotation'] }],
+ "react/no-unknown-property": ['error', { ignore: ['css', "args", 'wireframe', 'rotation-x', 'rotation', 'object', 'position', 'intensity'] }],
}
App.tsx
まず全体。
App.tsx
-import React, {useRef} from 'react';
+import React, { useRef, Suspense} from 'react';
import './App.css';
-import { Canvas, useFrame, MeshProps } from '@react-three/fiber'
+import { Canvas, useLoader, useFrame } from '@react-three/fiber'
import * as THREE from 'three'
import { OrbitControls, Environment } from '@react-three/drei'
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-const Box = (props: MeshProps) => {
+const TheModel = () => {
- const ref = useRef<THREE.Mesh>(null!)
+ const { scene, animations } = useLoader(GLTFLoader, "/animate-bones.glb");
+ const mixer = new THREE.AnimationMixer(scene);
+ mixer.clipAction(animations[0]).play();
+ mixer.clipAction(animations[1]).play();
- useFrame((_, delta) => {
+ useFrame((state, delta) => {
- if( !ref.current) return
- ref.current.rotation.x += 1 * delta
- ref.current.rotation.y += 0.5 * delta
+ mixer.update(delta);
});
return (
- <mesh {...props} ref={ref}>
- <boxGeometry />
- <meshNormalMaterial />
- </mesh>
+ <primitive object={scene} position={[0, 0, 0]} />
)
}
const App = () => {
return (
<div style={{ width: "100vw", height: "75vh" }}>
<Canvas camera={{ position: [3, 1, 2] }}>
+ <ambientLight intensity={2} />
+ <pointLight position={[40, 40, 40]} />
- <Box position={[1, 1, 1]} name="A" />
+ <Suspense fallback={null}>
+ <TheModel />
+ </Suspense>
<Environment preset="forest" background />
<OrbitControls />
<axesHelper args={[5]} />
<gridHelper />
</Canvas>
</div>
);
}
export default App;
で、実行。
出来た!!
すばらしい、簡単にできた。
まとめ
3Dモデルのアニメーションを実行するには、THREE.AnimationMixerを使うのがポイント。
THREE.AnimationMixerの使い方は、以下の通り。
1. new THREE.AnimationMixer() ← 引数にsceneを渡す。
↓
2. clipAction()で、THREE.AnimationMixerにアニメーション追加
↓
3. 追加したアニメーションをstart()
↓
4. useFrame()の中で、mixer.update()
で動くようになる。分かりやすっ!!
React+TypeScript+R3Fのtutorial応用編2(Octreeで衝突判定の絞り込み)
React+TypeScript+R3Fのtutorial応用編4(glTFで3Dアニメーション(モデルとモーション別々ファイル読込み))
Discussion