二つのベクトルを徐々に重ねる。

あるベクトル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
D3DXMATRIX M;
D3DXMatrixRotationAxis(&M, &A, D3DXToRadian(δ));

D3DXVECTOR3 P';
D3DXVec3TransformCoord(&P', &P, &M);

’(ダッシュ)を変数名に使ってますけど、実際C++じゃ使えませんのでご注意。


次に、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';
}


こんな感じです。コイツを何に使うのかと言うと、
例えばキャラクターの向き(姿勢)をベクトルで表していた場合に、
そのキャラの向きを、特定方向に徐々に近付ける処理なんかに使えるかなと。
クォータニオンとか使えばもっと楽に出来るのかもしれないけども。
向きをベクトルで持っておくと、移動ベクトルの計算とかで便利なんですよね。
まあそこら辺は作るアプリケーション次第になっちゃいますが、一例として。