【Csharp】XNAでIKの実装、その1

まずは単純に先端のボーンだけをIKのターゲットとなるボーンに向かせてみた。

とりあえず動画。

動画の左が先端のみ自力でIK計算したもので、右がBlender側でIK計算が適用された後の動作。

これだけだと、IKというよりは、単純に指定方向に向きを変えただけに過ぎないんだけれども、計算の核の部分は同じだ。

あとは、これをいくつかボーンをさかのぼって適用していくことと、複数回にわたって再度適用することで、ボーン全体がIKターゲットへ向かうようになる。

IK計算を計算式で表すと非常に難しく見えてしまうので、自分自身への復習がてら、どういうことをやっているのか文章で表現してみようと思う。

まず、ボーンといっているデータが何なのかというところから、きちんと定義して説明してみたい。

ボーンとは、ある局所座標上にあるマトリクス(スケール・移動・回転の情報)、これである。

局所座標というのは、ワールド座標上にある任意の点を原点とする座標系のことである。

特に、ボーンの局所座標というと、直接の親ボーンを原点とする座標系のことになる。

この局所座標がIKの計算では重要で、任意の局所座標へと座標変換する方法は下記となる。

局所座標上の位置=ワールド座標上の位置*親ボーンの逆行列

以上を前提に、あるボーンがIKターゲットとなるボーンの方向を向く計算は以下の手順となる。

1.局所座標上のIKターゲットの座標から方向ベクトルを求める。

IKターゲットへの方向ベクトル=IKターゲットのワールド座標*親ボーンの逆行列

2.向きを変えたいボーンの現在の局所座標上の方向ベクトルを求める。

ボーンの現在の方向ベクトル=ボーンのワールド座標*親ボーンの逆行列

そして、算出された値を正規化(Normalize)する。

これによりIKターゲットへ向かうベクトルとボーン自身のベクトルが同じ局所座標上に統合された。

ここから2の方向ベクトルが1の方向ベクトルと重なるような回転行列を求めればよいわけだが、そのために必要な情報は回転軸と回転角度となる。

3.1と2のドット積から2のベクトルを1のベクトルに重ねるための回転量(スカラー値)を求める。

回転量=1のベクトルと2のベクトルのドット積

4.この回転量から回転角度を求める

回転量=cos(回転角度)より、回転角度=Math.Acos(回転量)

次に回転軸を求める
5.1と2のクロス積から2のベクトルを1のベクトルに重ねるための回転軸(ベクトル)を求める。

回転軸=1のベクトルと2のベクトルのクロス積

6.求まった回転軸と回転角度から回転行列を求める。

回転行列=Matrix.CreateFromAxisAngle(回転軸、回転角度)

こうして、あるボーンがIKターゲットとなるボーンの方向を向くための回転行列が求まった。

4年前

コメントを残す

メールアドレスが公開されることはありません。