LoginSignup
14
6

VRM用のアニメーションファイル(.vrma)の簡単な作り方

Posted at

はじめに

みなさん こんにちは またはこんばんは、ギャルプロです💪

今回はブラウザ(threejs)で利用できるVRMにモーションをさせるためのアニメーションファイルを作成してみたいと思います!
なお、VRMにアニメーションをさせるコンポーネントはpixivさんのVRMAnimationを利用させていただきます✨

アニメーションファイルを準備する

今回はギャルプロちゃんに考える :thinking: ポーズをさせてみたいと思います。
アニメーションを作成するのはとても大変なので、ゲーム開発者にはお馴染み(?)のMixamoというサービスを利用します😳

まずはMixamoにアクセスし、好きなアニメーションを探します。(Adobeのアカウントが必要ですが無料で利用できます!神!)

好みのアニメーションが見つかったら、ダウンロードボタンを押し、画像のような設定でfbxファイルをダウンロードしましょう💪
image.png

FBXをglTFに変換する

さて、ダウンロードしたfbxファイルですが、このままではVRMにロードさせることができないので、glTFという形式に変換します。
変換にはMeta Incubator(旧Facebook Incubator)が提供している、FBX2glTFを使用します。
https://github.com/facebookincubator/FBX2glTF

インストールが完了したら、以下のようにfbxをglTFに変換してください。

path/to/FBX2glTF -i Thinking.fbx -o Thinking.glTF

buffer.binとThinking.gltfの2つのファイルが出力されれば完璧です!

glTFを編集する

VRMAnimationクラスが使用する.vrmaというフォーマットに変換するために、以下の2つのデータを付与します。

  1. glTF拡張の宣言
  2. ヒューマノイドのボーン情報

VRMコンソーシアム1によるVRMAの仕様については以下のページを参照してみてください!
※現時点ではドラフトなので変更される可能性があります
https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm_animation-1.0/README.ja.md

1.glTF拡張の宣言

glTFの拡張機能を利用していることを宣言するため、.glTFファイルを編集していきます :pencil:
glTF はただのjsonなのでVSCodeなどのエディタで開きます。

開いたら次のようなフィールドを追加してください!

"extensionsUsed": ["VRMC_vrm_animation"]

簡単ですね :sparkles:

2.ヒューマノイドのボーン情報

こちらが本作業のキモです。
Mixamoが吐き出したモーションのノードをVRMのヒューマノイドボーンにリターゲティングしていきます :muscle:

具体的にはアニメーションのglTFに含まれるnodesから対応するボーンのインデックスを確認する作業です。

たとえば glTFの中身が以下のようになっていたときに

"nodes": [
        {
            "name": "RootNode",
            "children": [1, 66, 67]
        },
        {
            "name": "mixamorig:Hips",
            "translation": [
                -7.72729080722456e-8, 1.04274868965149, 0.0155431581661105
            ],
            "rotation": [0.00645854603499174, 0, 0, 0.999979138374329],
            "children": [2, 56, 61]
        },
        ...
]

Hipsは1番目のノードなので

"extensions": {
    "VRMC_vrm_animation": {
        "specVersion": "1.0",
        "humanoid": {
            "humanBones": {
                "hips": {
                    "node": 1
                },
                ...
            }
        }
    }
}

というデータを作成することになります。

vrmaで利用するヒューマイノイドのボーン一覧はこちらから参照できました。

これは地道な作業となるのでチートシートを記載しておきます :joy:
以下のデータをglFTの末尾にコピペすればMixamoからダウンロードしてきたアニメーションは動くと思います!

MixamoからダウンロードしてきたglTFに対して追加するノード情報 :point_right:
"extensions": {
    "VRMC_vrm_animation": {
        "specVersion": "1.0",
        "humanoid": {
            "humanBones": {
                "hips": {
                    "node": 1
                },
                "spine": {
                    "node": 2
                },
                "chest": {
                    "node": 3
                },
                "upperChest": {
                    "node": 4
                },
                "neck": {
                    "node": 5
                },
                "head": {
                    "node": 6
                },
                "rightShoulder": {
                  "node": 8
                },
                "rightUpperArm": {
                    "node": 9
                },
                "rightLowerArm": {
                    "node": 10
                },
                "rightHand": {
                    "node": 11
                },
                "rightThumbMetacarpal": {
                    "node": 12
                },
                "rightThumbProximal": {
                    "node": 13
                },
                "rightThumbDistal": {
                    "node": 14
                },
                "rightIndexProximal": {
                    "node": 16
                },
                "rightIndexIntermediate": {
                    "node": 17
                },
                "rightIndexDistal": {
                    "node": 18
                },
                "rightMiddleProximal": {
                    "node": 20
                },
                "rightMiddleIntermediate": {
                    "node": 21
                },
                "rightMiddleDistal": {
                    "node": 22
                },
                "rightRingProximal": {
                    "node": 24
                },
                "rightRingIntermediate": {
                    "node": 25
                },
                "rightRingDistal": {
                    "node": 26
                },
                "rightLittleProximal": {
                    "node": 28
                },
                "rightLittleIntermediate": {
                    "node": 29
                },
                "rightLittleDistal": {
                    "node": 30
                },
                "leftShoulder": {
                    "node": 32
                },
                "leftUpperArm": {
                    "node": 33
                },
                "leftLowerArm": {
                    "node": 34
                },
                "leftHand": {
                    "node": 35
                },
                "leftThumbMetacarpal": {
                    "node": 36
                },
                "leftThumbProximal": {
                    "node": 37
                },
                "leftThumbDistal": {
                    "node": 38
                },
                "leftIndexProximal": {
                    "node": 40
                },
                "leftIndexIntermediate": {
                    "node": 41
                },
                "leftIndexDistal": {
                    "node": 42
                },
                "leftMiddleProximal": {
                    "node": 44
                },
                "leftMiddleIntermediate": {
                    "node": 45
                },
                "leftMiddleDistal": {
                    "node": 46
                },
                "leftRingProximal": {
                    "node": 48
                },
                "leftRingIntermediate": {
                    "node": 49
                },
                "leftRingDistal": {
                    "node": 50
                },
                "leftLittleProximal": {
                    "node": 52
                },
                "leftLittleIntermediate": {
                    "node": 53
                },
                "leftLittleDistal": {
                    "node": 54
                },
                "rightUpperLeg": {
                    "node": 56
                },
                "rightLowerLeg": {
                    "node": 57
                },
                "rightFoot": {
                    "node": 58
                },
                "rightToes": {
                    "node": 59
                },
                "leftUpperLeg": {
                    "node": 61
                },
                "leftLowerLeg": {
                    "node": 62
                },
                "leftFoot": {
                    "node": 63
                },
                "leftToes": {
                    "node": 64
                }
            }
        }
    }
}

.glTFを.vrmaに変換する

色々と方法があると思いますが、一番簡単なのは以下の方法でした。
VSCode拡張の「glTF Tools」をインストールします。
https://github.com/AnalyticalGraphicsInc/gltf-vscode

.gltfをエディターで開き、右クリック→glTF: Export To GLBを選択し、保存先のパスを指定します。
image.png

glbファイルが出来上がったら拡張子を.vrmaに変更します。

以上でVRMで利用できるアニメーションファイルができました :tada:

vrmaをロードして再生してみる

前のステップで作成したvrmaファイルをロードして再生してみましょう!
うまくいっていれば正しくモーション再生されるはずです🎉

今回は以上となります。
みなさんも良いVRMライフを!

バイビー

おまけ

DCCツール(Blenderとか)を使用せずに、glTF ⇄ glbの相互変換を行いたかったんだけど、なかなか良いイテレーション方法がなかったので、私のケースを記しておくね。

glb → glTF

glTF-Transformというプロジェクトを使ったよ!
https://gltf-transform.donmccurdy.com
Nodejsでも動くし、cliもあるからとっても便利💓

gltf-transform copy hoge.glb hoge.gltf

これで.binと.gltfが吐き出されます!

glTF → glb

これは上で紹介したようにVSCode拡張でやるのが便利だった!
gltf-transformにもpackの機能があるかなーって思ったんだけどチョットミツカラナカッタ🥺

おまけ2

Mixamoからダウンロードしてきたモーションだとチラつきが発生しちゃった:frowning2:
クォータニオンがなんか飛んでる気がしたからVRMAnimationのコードを直してIssue2を立てておいたよ!
もし同じ症状が発生している人がいたら見てみてね:v:

  1. https://vrm-consortium.org/

  2. https://github.com/pixiv/ChatVRM/issues/9

14
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
6