カメラにクォータニオンを実装する際に問題が発生しました。OpenGLで3Dスペースシューターを作成していますが、ジンバルロックを回避する必要があります。1つの軸だけで回転させると問題ありませんが、ピッチとヨーの両方を適用すると、奇妙な動作になります。私の回転角は私のマウスの入力を使用しています。
ここで、ViewMatrixを計算し、フレームごとに更新します
Matrix4x4 camera::GetViewMat()
{
m_rotation.AddX((oInput.MousePosition.GetY() - oInput.PrevMousePosition.GetY()) * m_sensitivity * dt);
m_rotation.AddY((oInput.MousePosition.GetX() - oInput.PrevMousePosition.GetX()) * -m_sensitivity * dt);
Matrix4x4 oTranslateOrigin, oRotate, oView;
oView.SetIdentity();
//constructor creates a quaternion from an AxisAngle, the constructor will be shown below
Quaternions pitch = Quaternions(m_rotation.GetX() * Utility::DegToRad(), Vector3(1, 0, 0));
Quaternions yaw = Quaternions(m_rotation.GetY() * Utility::DegToRad(), Vector3(0, 1, 0));
//update orientation with the new quaternion times its current orientation
ori = ori * yaw * pitch;
//convert quaternion to matrix, also shown below
oRotate = ori.ToMatrix();
oTranslateOrigin.BuildTranslate(-m_camPosition.GetX(), -m_camPosition.GetY(), -m_camPosition.GetZ());
oView = oRotate * oTranslateOrigin;
return oView;
}
ProjectionMatrixを初期化します
Matrix4x4 camera::GetProjMat(float fFieldOfViewY, float fAspectRatio, float fNearZ, float fFarZ)
{
// Transposed version of D3DXMatrixPerspectiveFovRH
float fYScale = 1 / tanf( fFieldOfViewY / 2.0f );
float fXScale = fYScale / fAspectRatio;
memset( &m_projMat, 0, sizeof( Matrix4x4 ) );
m_projMat.Set(0, 0, fXScale);
m_projMat.Set(1, 1, fYScale);
m_projMat.Set(2, 2, fFarZ / ( fNearZ - fFarZ ));
m_projMat.Set(2, 3, ( fNearZ * fFarZ ) / ( fNearZ - fFarZ ));
m_projMat.Set(3, 2, -1.0f);
return m_projMat;
}
これは、AxisAngleのクォータニオンを作成するコンストラクターの1つです。
Quaternions::Quaternions(float angle, Vector3& axis)
{
FromAxisAngle(angle, axis);
}
void Quaternions::FromAxisAngle(float angle, Vector3& axis)
{
float halfAngle = angle * ((float)PI/360.0f);
float sin = sinf(halfAngle);
this->w = cosf(halfAngle);
this->x = axis.GetX() * sin;
this->y = axis.GetY() * sin;
this->z = axis.GetZ() * sin;
}
Matrix4x4 Quaternions::ToMatrix()
{
Normalize();
Matrix4x4 mat;
mat.SetIdentity();
mat.Set(0, 0, 1.0f - 2*(this->y * this->y) - 2*(this->z * this->z));
mat.Set(0, 1, 2*(this->x*this->y) - 2*(this->w*this->z));
mat.Set(0, 2, 2*(this->x * this->z) + 2*(this->w * this->y));
mat.Set(1, 0, 2*(this->x * this->y) + 2*(this->w * this->z));
mat.Set(1, 1, 1.0f - 2*(this->x * this->x) - 2*(this->z * this->z));
mat.Set(1, 2, 2*(this->y * this->z) - 2*(this->w * this->x));
mat.Set(2, 0, 2*(this->x * this->z) - 2*(this->w * this->y));
mat.Set(2, 1, 2*(this->y * this->z) + 2*(this->w * this->x));
mat.Set(2, 2, 1.0f - 2*(this->x * this->x) - 2*(this->y * this->y));
return mat;
}
それが私がしていることです。
皆さんは私を正しい方向に導いてくれますか?