2軸の向きから回転マトリクスを作る

 回転行列の列ベクトルは、基本座標系における x, y, z の単位ベクトルを示しとります。

 ということは、あるオブジェクトの姿勢を決定する材料がベクトルしかのうても、代入演算のみで回転マトリクスを作ることができるということです。状況によっては、けっこう便利じゃいうことに先日気がつかされました。

 Y-up ベクトルと Z の向きが分かっとりゃあ、 X は外積で計算することができるけぇ、最低2軸の向きが分かっとりゃあ回転マトリクスを作れます。

Matrix mtx = Matrix::Identity;
mtx.m11 = xVec.x;
mtx.m21 = xVec.y;
mtx.m31 = xVec.z;

mtx.m12 = yVec.x;
mtx.m22 = yVec.y;
mtx.m32 = yVec.z;

mtx.m13 = zVec.x;
mtx.m23 = zVec.y;
mtx.m33 = zVec.z;

 Y-up と向きベクトルが直行しているかどうかは、代入の時点で保障されとかにゃあいけん。ほいじゃけど、ベクトルから回転マトリクスを作りたいようなシーンでは*1、たいがい直行しとらん。

 たとえば、xY-up が Y+1 で、向きが Z+1 のオブジェクトがあり、このオブジェクトが地勢ジオメトリの傾斜を移動し、傾斜面に沿ってピッチを上げたとする。地勢ジオメトリの法面から新たな Y-up ベクトルが得られるけど、それは水平を保っていた時の Z+1 の向きベクトルとは直行せんことになる。

 こがあな場合は、 Y-up と向き(Z)ベクトルの外積から X(right) ベクトルを求めた後、 Y-up と X の外積から新しい Z ベクトルを得ることで、それぞれ直行の関係にある3つのベクトルを得ることができます。

void AxesToMatrix(const Vector3& yDir, const Vector3& zDir, Matrix* pOut)
{
  Vector3 xDir = yDir.Cross(zDir);
  Vector3 new_zDir = yDir.Cross(xDir);

  pOut->Identity();
  pOut->m11 = xDir.x;
  pOut->m21 = xDir.y;
  pOut->m31 = xDir.z;

  pOut->m12 = yDir.x;
  pOut->m22 = yDir.y;
  pOut->m32 = yDir.z;

  pOut->m13 = zDir.x;
  pOut->m23 = zDir.y;
  pOut->m33 = zDir.z;
}

 この方法は軸固定回転に便利で、外積の取り方で固定する軸を変えられるけぇ、いろいろ使いでがあります。

*1:ばらばらに制御されているベクトルから姿勢を決定したいという状況でしょうから