PMXのIKの設定(ループ回数・単位角・角度制限)|実物の値とthree.jsでの解き方
足IKを動かすと脚が曲がって足首が付いてくるのは、IKボーンに書かれた設定に従って、ひざと足を少しずつ回しているからです。PMXに書かれている設定の中身と、ブラウザ(three.js)での解き方、その設定がどれくらい効いているかをまとめます。
IKボーンに書かれているもの
| 項目 | 意味 |
|---|---|
| ターゲット | 届かせたいボーン(足IKなら足首)。目標の位置はIKボーン自身 |
| ループ回数 | リンクを順に回す処理を何周するか |
| 単位角 | 1回の回転で回してよい角度の上限(ラジアン) |
| リンク | 回してよいボーンの一覧(足IKなら ひざ → 足 の順)。リンクごとに角度制限を持てる |
実物の値
| IK | 人物A | アリシア |
|---|---|---|
| 足IK | 40回・単位角114.59°(2ラジアン)・リンク2本 | 40回・57.30°(1ラジアン)・リンク2本 |
| つま先IK | 3回・229.18°(4ラジアン)・リンク1本 | 3回・57.30°・リンク1本 |
| 髪IK | 10回・5°・リンク8本(左右) | 10回・5°・リンク8本(左右)。三つ編みIKは4本 |
| 腕IK(左腕IK付きの版だけ) | 20回・57.30°・リンク2本 | - |
角度制限が付いているのは、どのモデルも「ひざ」だけで、X軸だけが -180°〜-0.5°、Y軸・Z軸は0〜0でした。ひざが前後の一方向にしか曲がらず、まっすぐ伸びきることもない(0.5°は残る)という指定です。足と足首には制限がありません。
同じ足IKでも、単位角は人物Aが2ラジアン、アリシアが1ラジアンで、作者によって違います。どちらも1回でかなり大きく回せる値で、足IKでは上限として効く場面は少ないはずです。髪IKの5°は小さく、少しずつしか曲がりません。
three.jsでの解き方
three.js(r171)は CCDIKSolver で解きます。リンクを順に「効果ボーン(足首)を目標へ向ける回転」で回し、これをループ回数だけ繰り返す方法(CCD)です。PMXの設定は次のように使われます。
- ループ回数はそのまま繰り返しの回数になります。1周の中でどのリンクも回らなかったら、そこで打ち切ります
- 単位角は1回の回転の上限として使います(PMDの値は4倍して使う、とソースにあります)
- 角度制限は、回したあとのオイラー角を下限・上限の範囲に切り詰めて当てます。座標系の違いを直すため、X・Yの符号を入れ替えてから使います(ひざは three.js の上では X が 0.5°〜180°)
- PMDには角度制限の欄がありません。 MMDLoader は、名前に「ひざ」を含むリンクをX軸だけで回すよう決め打ちしています
物理で動くボーンのIKは解かれない
MMDAnimationHelper は物理演算を有効にすると、剛体の種類が1か2(物理で動く)のボーンをリンクに持つIKを止めます。リンクを順に見て、物理で動くリンクに当たったところでそのIKの処理を打ち切る作りです。
実物では、髪IKのリンクは人物Aもアリシアも全部が剛体の種類2でした(三つ編みIKも同じ)。物理を有効にしている限り、髪IKは1度も解かれず、髪は物理だけで動きます。足IK・つま先IKのリンクの剛体は種類0(ボーン追従)で、こちらは毎フレーム解かれます。
ループ回数を減らすと、足首はどれだけ離れるか
人物Aに実物のダンスVMD(約4分)を当て、再生時間を100等分した各時点で、IKを解く前の姿勢へ戻してから足IKのループ回数だけを変えて1回解き、足首と足IKボーンの距離を測りました。脚を伸ばしきっても届かない時点(股関節から目標までが、もも+すねの長さ10.24ユニットより遠い)は、200か所中10か所あったので除いています。
| 足IKのループ回数 | 距離の中央値 | 0.1ユニットより離れた時点 |
|---|---|---|
| 1回 | 1.41 | 184 / 190 |
| 3回 | 1.13 | 182 / 190 |
| 10回 | 0.56 | 144 / 190 |
| 40回(モデルの指定) | 0.0006 | 40 / 190 |
1ユニットはおよそ8cmなので(MMDのスケールと単位)、10回では足首が中央値で4.5cmほど目標から浮きます。モデルが40回と書いているのには意味があり、処理を軽くするために回数を減らすと、足が床から浮いたり滑ったりします。
40回でも、0.1ユニット以上離れたままの時点が190中40ありました(最大0.335)。別のダンスVMDでは、届く位置なのにすべての時点で0.27〜0.32離れ、ループ回数を変えてもほとんど縮みませんでした。同じ姿勢のまま解き直すと5回目で0.0004まで縮むので、届かない位置ではありません。原因はまだ特定できておらず、MMD本体で同じ姿勢がどうなるかも比べられていません。