"そこ"から這い上がるブログ

プログラミングと電子工作が趣味でそこら辺のことを備忘録的に書きつつ這い上がっていこうといったブログ。そこ這い。

ベクトルを同じ向きにするための回転行列の求め方

ある方向を示すベクトルAがあって、他のベクトルBをその方向に向けたい場合に

回転行列の求め方に悩んだのでメモ。

やり方としては

  1. AとBの内積からなす角( 回転量 )を求める。
  2. AとBの外積から 回転軸 を求める。
  3. 回転量回転軸 から回転行列を作る。

といった感じです。

// toVec, fromVecは正規化されているVector3f
// 二つのなす角( 内積を求める )
float angle = acos( fromVec.dot( toVec ) );
// 回転軸( 外積を求めて正規化 )
Eigen::Vector3f axis = fromVec.cross( toVec ).normalized();
// 回転量と回転軸から回転行列を生成
Eigen::Matrix3f rotateMat = Eigen::AngleAxisf( angle, axis ).matrix();

Eigenを使った例ですが、考え方自体はUnityなどでも使えるはずです。

回転量と回転軸から行列を求めるのにEigen::AngleAxisfクラスを使用して楽をしてしまっていますが、

ロドリゲスの回転公式 を使うと求められるはず

EigenではAffineクラスを使って移動(+拡大)も含めたアフィン変換の行列の生成もできます。

// クォータニオン
Eigen::Quaternionf quat( Eigen::AngleAxisf( angle, axis ) );
// アフィンクラス
Eigen::Affine3f affine;
// 移動量
Eigen::Translation3f translation( Eigen::Vector3f( 0.5f, 1.5f, 0 ) );
// 移動と回転の合成
affine = translation * quat;
// 行列の取得
Eigen::Matrix4f affineMat = affine.matrix();

にしてもベクトルってのはすごい便利だなぁ

参考先