二つのベクトルを徐々に重ねる。
あるベクトルPを、あるベクトルQに重なるように、徐々に変化させる計算方法。
補完とかとはちょっと違う感じ。媒介変数とかは使いません。
変化のさせ方は、ベクトルPとベクトルQのなす平面に垂直な軸に対して、
回転させてPとQの成す角を近付けていく感じ。
ただし、PとQの成す角は使わず、PとQ、後は一回の角度変化量δだけ使います。
毎計算でδだけ近付けて、PがQに重なった、もしくはPがQを超えたと判断したら
回転終了になる感じ。
まず回転軸の算出。便宜上Direct3Dの関数を交えたコードで説明していきます。
// 回転軸A = P×Q
D3DXVECTOR3 A;
D3DXVec3Cross(&A, &P, &Q);
if (D3DXVex3LengthSq(&A) == 0.0f) {
// 軸=外積がゼロなので、既に重なっている。回転終了。
exit;
}
D3DXVec3Normalize(&A, &A); // 軸の正規化
次は適当な変化量δで回転させたベクトルP'の計算。
// P' = PM’(ダッシュ)を変数名に使ってますけど、実際C++じゃ使えませんのでご注意。
D3DXMATRIX M;
D3DXMatrixRotationAxis(&M, &A, D3DXToRadian(δ));D3DXVECTOR3 P';
D3DXVec3TransformCoord(&P', &P, &M);
次に、P'とQの外積、即ち次の計算の時の回転軸A'を計算。
この時点で、P'とQが重なれば、回転終了。
// A' = P'×Q
D3DXVECTOR3 A';
D3DXVec3Cross(&A', &P', &Q);
if (D3DXVex3LengthSq(&A') == 0.0f) {
// P'がQにちょうど重なった。回転終了。
P = P';
exit;
}
D3DXVec3Normalize(&A', &A'); // 軸の正規化
重なっていない場合は、P'がQを通過したかどうかを調べます。
P'がQを通過した場合は、PとQの左右関係と、P'とQの左右関係が
変わるはずで、A = P×Qと、A' = P'×Qの向きが正反対になるはずなので、
それを内積A・A'を使って調べます。正反対になっていれば、
内積は負の数値になるはず。
// A・A'を取って向き関係を調べる
if (D3DXVec3Dot(&A, &A') < 0.0f) {
// 結果が負になったので、P'はQを通過した。回転終了。
P = P';
exit;
} else {
// まだP'はQを通過していないので、先頭の計算に戻る。
P = P';
}
こんな感じです。コイツを何に使うのかと言うと、
例えばキャラクターの向き(姿勢)をベクトルで表していた場合に、
そのキャラの向きを、特定方向に徐々に近付ける処理なんかに使えるかなと。
クォータニオンとか使えばもっと楽に出来るのかもしれないけども。
向きをベクトルで持っておくと、移動ベクトルの計算とかで便利なんですよね。
まあそこら辺は作るアプリケーション次第になっちゃいますが、一例として。