お約束どおり、カメラが常に空間の特定のポイントを向くようにする方法を示すコードです。
まず、角度と軸からクォータニオンを構築するメソッドが必要です。たまたまペーストビンにあるのですが、角度の入力はラジアンです。
http://pastebin.com/vLcx4Qqh
軸 (0,0,0) を入力しないように注意してください。これはまったく意味がありません。
次に、実際の更新方法として、カメラをデフォルトの向きからターゲット ポイントに向けるクォータニオンを取得する必要があります。私は頭のてっぺんからこれを書いたことに注意してください。おそらく少しデバッグが必要で、少し最適化が必要かもしれませんが、これは少なくとも正しい方向へのプッシュを与えるはずです。
void camera::update()
{
// First get the direction from the camera's position to the target point
vec3 lookAtDir = m_targetPoint - m_position;
// I'm going to divide the vector into two 'components', the Y axis rotation
// and the Up/Down rotation, like a regular camera would work.
// First to calculate the rotation around the Y axis, so we zero out the y
// component:
vec3 lookAtHorizontal = vec3(lookAtDir.x, 0.0f, lookAtDir.z).normalize();
// Get the quaternion from 'default' direction to the horizontal direction
// In this case, 'default' direction is along the -z axis, like most OpenGL
// programs. Make sure the projection matrix works according to this.
float angle = acos(vec3(0.0f, 0.0f, -1.0f).dot(lookAtHorizontal));
quaternion horizontalOrient(angle, vec3(0.0f, 1.0f, 0.0f));
// Since we already stripped the Y component, we can simply get the up/down
// rotation from it as well.
angle = acos(lookAtDir.normalize().dot(lookAtHorizontal));
if(angle) horizontalOrient *= quaternion(angle, lookAtDir.cross(lookAtHorizontal));
// ...
m_orientation = horizontalOrient;
}
実際にm_orientation
世界m_position
を取得して取得する -> カメラ行列
// First inverse each element (-position and inverse the quaternion),
// the position is rotated since the position within a matrix is 'added' last
// to the output vector, so it needs to account for rotation of the space.
mat3 rotationMatrix = m_orientation.inverse().toMatrix();
vec3 inverseTranslate = rotationMatrix * -m_position; // Note the minus
mat4 matrix = mat3; // just means the matrix is expanded, the last entry (bottom right of the matrix) is a 1.0f like an identity matrix would be.
// This bit is row-major in my case, you just need to set the translation of the matrix.
matrix[3] = inverseTranslate.x;
matrix[7] = inverseTranslate.y;
matrix[11] = inverseTranslate.z;
編集 明らかだと思いますが、完全を期すために、 .dot() はベクトルの内積を取り、 .cross() は外積を取り、メソッドを実行するオブジェクトはベクトル A であり、メソッドのパラメータはベクトルですB.