【Blender】ひとつのArmatureに複数のアクションを統合する

<!-- ==================================================== -->
# 概要
<!-- ==================================================== -->
Three.js（React Three Fiber）でglbモデルを扱うときに、[Maximo](https://www.mixamo.com/)からモデルをお借りする場合、Maximoからダウンロードできるファイルはfbx形式なので、一度Blenderでglb形式にエクスポートしてからThree.jsにインポートするという手順を踏んでいます。

Maximoからダウンロードできるファイルは、以下のようになっています。

* スキン（TPose）だけのモデル
* アニメーションだけのモデル
* スキン + アニメーションのモデル

さらに、それぞれに対してアーマチュアの情報が含まれます。
このため、1つのモデルで複数のアクションを扱うときに、そのままモデルと各アニメーションファイルを別々に扱うとアーマチュアの情報が重複して、ファイルサイズが大きくなってしまいます。
また、glbファイルを個別にインポートすると、その分ロード時間が長くなります。

:::note info
この記事では、ひとつのArmatureに複数のアクションを統合する手順について、Mixamoモデルを使用してまとめました。
:::

<!-- ==================================================== -->
# 使用するモデル
<!-- ==================================================== -->
使用するモデルは、Mixamoから以下のものをお借りしました。

* [Y Bot](https://www.mixamo.com/#/?page=1&query=Ybot&type=Character)
* [Swing Dancing](https://www.mixamo.com/#/?page=1&query=dance&type=Motion%2CMotionPack)
* [Hip Hop Dancing](https://www.mixamo.com/#/?page=1&query=dance&type=Motion%2CMotionPack)
* [Wave Hip Hop Dance](https://www.mixamo.com/#/?page=1&query=dance&type=Motion%2CMotionPack)

下3つはアニメーションのみダウンロードしています。

![スクリーンショット 2022-01-19 183105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/51483846-5e1c-88bd-3a80-5250fba43eb8.png)

<!-- ==================================================== -->
# ファイルの統合
<!-- ==================================================== -->
### スキンモデルの追加
Blenderでスキンモデル（ybot.fbx）をインポートします。
![スクリーンショット 2022-01-19 183520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/ced2bed4-40e9-8c3b-919d-5d95d9355fea.png)

### NLA（Non Linear Animation）にスタッシュする
glbファイルでエクスポートできるアニメーションは、オブジェクトのアクティブアクション（オブジェクトに1対1で割り振られたアクション）か、NLAトラックに格納されているアクションになります。
（詳しくは、[ドキュメント](https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html#export)参照）

今回のように、複数のアクションを扱いたい場合は、NLAトラックにスタッシュする必要があります。

スキンモデルには、TPoseのアクションとして`Armature|mixamo.com|Layer0`が割り振られているので、これをNLAトラックにスタッシュします。

画面下部から、ノンリニアアニメーション画面に移動して、スタッシュします。
![スクリーンショット 2022-01-19 184927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/12d76a75-466d-a252-f090-142bbed07fa4.png)
![スクリーンショット 2022-01-19 185057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/c573f969-b8ad-02f0-54ea-e97e79fc3729.png)

必須ではないですが、アクション名をわかりやすくするために、`Armature|mixamo.com|Layer0`を`TPose`にリネームしています。

![スクリーンショット 2022-01-19 185410.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/22fef15d-cb02-18ce-e774-db51240aabf5.png)
![スクリーンショット 2022-01-19 185501.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/07ce2836-76b1-add0-e09c-4b8bdbf26ff3.png)

### アニメーションファイルの追加
アニメーションファイル（Swing Dancing.fbx）をインポートします。
**スタッシュはしない**で、リネームだけ行います。
![スクリーンショット 2022-01-19 185848.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/eff2b055-eb79-a4ef-8b5e-6c488c698ab5.png)

### アクションの統合
[ドーフシート]から[アクション]に移動して、親のArmature（TPoseの方）を選択します。
![スクリーンショット 2022-01-19 190042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/fc518261-7c45-bdb6-d6d4-1c0bf4c07cfc.png)
![スクリーンショット 2022-01-19 190111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/6aea7576-2585-98a7-eac1-30d907834cd4.png)
![スクリーンショット 2022-01-19 190244.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/4941c33b-6e74-fc99-48fc-a8099094aab0.png)

この状態で、[Swing]アクションを選択します。
![スクリーンショット 2022-01-19 190457.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/745f7b83-ed45-0edf-5c50-4b81483b52af.png)
そうすると、[Swing]アクションが親のArmatureに統合されます。
ツリーを見ると、[Swing]アクションがアクティブアクションとなっているので、ノンリニアアニメーション画面に移動してこれをスタッシュします。
![スクリーンショット 2022-01-19 190818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/c233a99e-4d3c-ceb3-f2b7-8a5c8a979e0d.png)
![スクリーンショット 2022-01-19 190915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/57256467-1272-ab5f-80d5-3e2e877ef359.png)

`Swing Dancing.fbx`からインポートしたArmatureは削除します。

これで統合ができました！
あとは、統合したいアクションの数だけ同じことを繰り返すだけです。
![スクリーンショット 2022-01-19 191503.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/0f01eb0a-974b-8434-7894-a831c1bae5b3.png)

<!-- ==================================================== -->
# 確認（React Three Fiber）
<!-- ==================================================== -->
React Three Fiberでglbファイルを扱う場合、インポート用の雛形ファイルを生成してくれる便利なサイトがあります。
ここで、統合したアクションが含まれているか確認してみます。

https://gltf.pmnd.rs/

![スクリーンショット 2022-01-19 192011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/53279211-1a87-0cd4-cf17-6176563401fc.png)

コントローラーの`types`にチェックを入れると、TypeScript用の型付きのコードが生成されます。
ここで、`ActionName`に統合したアクションの名前が入っていればOKです。
また、glbファイルにアニメーションが含まれる場合、`useAnimations`が使用されます。雛形では`actions`しか受け取っていませんが、`names`を参照することでアクション名の配列を受け取れます。

```.tsx
const { actions, names } = useAnimations(animations, group)
```

<!-- ==================================================== -->
# 参照
<!-- ==================================================== -->
https://www.youtube.com/watch?v=V7FZ_O1IkxE

https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html#animation