PMXのボーンのフラグと変形階層|実物で数えた使われ方とthree.jsでの扱い
PMXのボーンには、名前と位置のほかに「何ができるボーンか」を表すフラグと、変形の順番を決める変形階層が書かれています。再生に効くものと、編集画面のためのものがあります。
フラグの一覧と、実物での数
| ビット | 意味 | 人物A(ad_ik2) | アリシア | ステージ |
|---|---|---|---|---|
| 0x0001 | 接続先をボーンで指定する(しないときは位置のずれで指定) | 249 | 77 | 0 |
| 0x0002 | 回転できる | 314 | 150 | 15 |
| 0x0004 | 移動できる | 25 | 14 | 15 |
| 0x0008 | 表示する | 241 | 130 | 15 |
| 0x0010 | 操作できる | 312 | 133 | 15 |
| 0x0020 | IK | 7 | 7 | 0 |
| 0x0080 | ローカル付与 | 0 | 0 | 0 |
| 0x0100 | 回転付与 | 53 | 21 | 0 |
| 0x0200 | 移動付与 | 0 | 1 | 0 |
| 0x0400 | 軸固定 | 8 | 5 | 0 |
| 0x0800 | ローカル軸 | 154 | 66 | 0 |
| 0x1000 | 物理後変形 | 0 | 0 | 0 |
| 0x2000 | 外部親変形 | 0 | 0 | 0 |
ボーンの数は人物Aが314本、アリシアが150本、ステージが15本です。人物Aでは73本が「表示しない」、2本が「操作できない」になっていました。どちらも編集画面での見え方と扱いを決めるもので、再生には関係しません。
フラグで、後ろに続く項目が変わる
ボーンのレコードは長さが一定ではありません。フラグが立っているときだけ、後ろに項目が続きます。自前でPMXを読むときは、この順に進める必要があります。
| フラグ | 続く項目 |
|---|---|
| 0x0001 が立っていない | 接続先の位置のずれ(Float32×3)。立っていればボーンの番号 |
| 0x0100 か 0x0200 | 付与元のボーンの番号と付与率(Float32) |
| 0x0400 | 固定する軸の向き(Float32×3) |
| 0x0800 | ローカル軸のX・Zの向き(Float32×3 を2つ) |
| 0x2000 | 外部親のキー(Int32) |
| 0x0020 | IKの設定(ターゲット・繰り返し回数・1回の角度の上限・リンクの一覧) |
three.jsが使っているもの、使っていないもの
- IK: 使います。人物Aの足IKは繰り返し40回・リンク2本(ひざに角度の制限が1つ)、つま先IKは3回・1本でした。髪IKはリンク8本です。
- 回転付与: 使います。ローカルでない回転付与だけです(移動付与とローカル付与は TODO のまま。付与親)。
- 軸固定・ローカル軸: 読み込むだけで使いません。VMDには回転が四元数でそのまま書かれているので、再生でこの2つを使う場面はありません。編集画面でボーンを回す向きを決めるための情報です。
- 表示・操作できる: 使いません(three.jsには編集画面が無いため)。
- 物理後変形・外部親変形: 使いません。実物の3体とステージでは、どちらも0本でした。
変形階層は、既定では無視される
変形階層は、ボーンを変形する順番を決める数字です。MMDは階層の小さい順、同じ階層ならボーンの番号順に、IKと付与を解きます。人物Aでは62本が階層1(足IK・つま先IK・髪IK・ひじ補助・足D・足先EX・足の指)、4本が階層2(目と目戻)で、残りは0でした。アリシアは全部0です。
three.jsのMMDAnimationHelperは、既定(pmxAnimation: false)では変形階層を見ません。 モーションを当てたあと、全部のIKを解き、次に全部の付与を解く、という順番に固定されています。付与どうしの依存(付与元が別の付与を受けている)は、親から順に解くよう並べ替えています。このサイトの再生も既定のまま使っています。
実物の3体で、この固定の順番で食い違いが出る形の依存があるかを調べました。IKのリンクに付与先のボーンが入っているものは1本もありませんでした。 付与の連鎖(人物Aの「右目戻」←「右目」←「両目」など)は親から順に解かれ、足D(←足)のようにIKで曲がるボーンから付与を受けるものは、IKを先に解くので曲がった後の値を受け取ります。この3体については、階層を無視しても順番が逆になる組み合わせは見つかりませんでした。
付与先が付与元より前の番号にあるボーン(人物Aの「ひじ補助」「右目」「左目」)もありましたが、three.jsは番号順ではなく付与の親子で並べ替えるので、ここも順番は崩れません。