VMDファイルの中身
VMDは「ヘッダ + モデル名 + 6つのブロック」という素直な形式です。自前のパーサを書いて実物31本で読み書きを往復させたときに分かったことをまとめます。
全体の構造
先頭からこの順に並びます。数値はすべてリトルエンディアン、文字列はShift_JISです。古いVMDでは後ろのブロックが存在しないことがあるので、読めるところまで読んで打ち切る作りにしないと落ちます。
| 位置 | 内容 | 1件あたり |
|---|---|---|
| 0〜29 | ヘッダ(Vocaloid Motion Data 0002 + 埋め) | 30バイト |
| 30〜49 | モデル名(Shift_JIS) | 20バイト |
| 以降 | モーション数(uint32)+ 本体 | 111バイト |
| 表情数 + 本体 | 23バイト | |
| カメラ数 + 本体 | 61バイト | |
| 照明数 + 本体 | 28バイト | |
| セルフ影数 + 本体 | 9バイト | |
| IK/表示数 + 本体 | 可変(9 + 21×IK数) |
ボーンのキーフレーム(111バイト)
- ボーン名 15バイト(Shift_JISの固定長。足りない分は0埋め)
- フレーム番号 4バイト(uint32)。MMDは30fps固定なので、番号÷30が秒
- 位置 12バイト(float32 × 3)。初期姿勢からの差分であって絶対座標ではない
- 回転 16バイト(クォータニオン float32 × 4)
- 補間曲線 64バイト
ボーン名が15バイトを超えると入りません。 Shift_JISの日本語は1文字2バイトなので、日本語だけなら7文字までです。書き出す側は必ず往復できるかを確かめてください。
補間はどこに効くのか
VMDの補間は「同じボーンのキーフレームどうし」の間でしか働きません。 30フレーム目でだけ腕を上げたつもりでも、そのボーンに他のキーフレームが無ければ、0フレーム目から最後まで上がったままになります。
手でモーションを作るときは、動かしていないところにも「元の姿勢」を明示的に置く必要があります。このサイトのモーション作成機能は、登録した全キーフレームのボーン名の和集合を取り、書かれていないところへ初期姿勢を書き込んでいます。
種類(モーション・表情・カメラ・照明)の見分け方
VMDのファイル自体に「これはカメラです」という印はありません。どのブロックに何件入っているかで判断します。 このサイトは次の順で判定しています(現行のmmdbox.netと同じ閾値)。
| 判定 | 条件 |
|---|---|
| モーション | ボーンのキーフレームが10件を超える |
| 表情 | 表情が10件を超え、ボーンが10件以下 |
| カメラ | カメラが10件を超え、ボーンが10件以下 |
| 照明 | 照明が1件以上あり、ボーンとカメラが10件以下 |
| 不明 | 上のどれにも当てはまらない |
照明だけ閾値が0なのは、光の色を数フレームだけ変えるファイルが実際に多いためです。10件を境にすると、そういうファイルが「不明」に落ちます。
書き出すときに気をつけること
- レコードは生バイト列のまま持ち回るほうが安全。 補間曲線64バイトのような触る必要のないデータを構造体へ展開して書き戻すと、往復で取りこぼしが起きます。トリミングや結合で必要なのは「どのレコードを残すか」と「フレーム番号を書き換えること」だけです。
- 2つのVMDを繋ぐときは、後ろのVMDをずらしてから連結する。 どちらも0フレーム目から始まるので、そのまま結合すると同じ(ボーン, フレーム)が重複して壊れます。
- 速度を上げると、丸めで同じ(ボーン, フレーム)が重なる。 落とした件数は利用者に見せるべきです(黙って捨てると、なぜ短くなったのか分かりません)。