2012-03-25 21 views
8

私は現在の回転が四元数として格納された3Dカメラを持っており、正しく回転させることができません。カメラを各フレーム(1人称シューティングゲーム)のマウスの動きに基づいてローカル軸周りに徐々に回転させたいが、回転は間違っている。それは作品のようなものですが、カメラは前方軸の周りを回転しないように見えます。クォータニオンカメラ。どのように正しく回転させるには?

私は回転にこの機能を持つ各フレーム更新:

void Camera::rotate(const Quat& q) 
{ 
    // m_rot is the current rotation 
    m_rot = m_rot * q; 
} 

はここに私の四元数の乗算機能があります:

Quat Quat::operator*(const Quat &rhs) const 
{ 
    // quaternion elements in w,x,y,z order 
    Vector4d res; 

    res[0] = m_q[0]*rhs.m_q[0] - m_q[1]*rhs.m_q[1] - 
      m_q[2]*rhs.m_q[2] - m_q[3]*rhs.m_q[3]; 
    res[1] = m_q[0]*rhs.m_q[1] + m_q[1]*rhs.m_q[0] + 
      m_q[2]*rhs.m_q[3] - m_q[3]*rhs.m_q[2]; 
    res[2] = m_q[0]*rhs.m_q[2] - m_q[1]*rhs.m_q[3] + 
      m_q[2]*rhs.m_q[0] + m_q[3]*rhs.m_q[1]; 
    res[3] = m_q[0]*rhs.m_q[3] + m_q[1]*rhs.m_q[2] - 
      m_q[2]*rhs.m_q[1] + m_q[3]*rhs.m_q[0]; 

    return Quat(res); 
} 

私が何か間違ったことをやっている、またはこれは、浮動小数点エラーのいくつかの種類ですもの?

+0

Qの乗法が正しいようです。それは浮動小数点のものかもしれません、または 'Camera :: rotate'への間違った引数かもしれません。その関数へのすべての呼び出しをログに記録し、 'q'と' m_rot'の両方をファイルに書き込んで解析します。 –

+0

関連:http://stackoverflow.com/questions/16384571/rotate-a-quaternion – danijar

答えて

7

問題を解明しました。私が行っているようなマウス制御の一人称カメラの場合、私は上下に見えるようにローカルのx軸を回転したいが、左右に向かって見るためにはグローバルなy軸を回転させたい。

これは、x軸に対して正しいです:

m_rot = m_rot * q; 

しかし、私は、y軸のためにこれを実行する必要があります。

m_rot = d * m_rot; 
0

私はどのようにすべての作業例を見つけることができなかったのでDirectXMathを使って一人称カメラをセットアップしました。私が2日間ソリューションに取り組んでいたので、ここに私のソリューションを掲載することに決めました。おそらく、同じ問題に取り組んでいる人がいるでしょう。私の解決策は最適化されていませんが、その背後にある数学は正しいはずです。

inline DX11FRAMEWORK_API DirectX::XMFLOAT4X4 MatrixCameraFirstPersonQuaternion(DirectX::XMFLOAT3 &Pos, DirectX::XMFLOAT3 &DeltaPos, DirectX::XMFLOAT3 &DeltaAngles, 
     DirectX::XMVECTOR &RotationQuaternion, DirectX::XMFLOAT3 *At = nullptr, DirectX::XMFLOAT3 *Up = nullptr) 
{ 
    using namespace DirectX; 

    static const XMFLOAT3 OriginalAt = { 1.f, 0.f, 0.f }; 
    static const XMFLOAT3 OriginalUp = { 0.f, 1.f, 0.f }; 
    static const XMFLOAT3 OriginalRight = { 0.f, 0.f, 1.f }; 

    // performing rotation of x-axis (here roll) und z-axis (here pitch) round camera axis using quaternion 
    RotationQuaternion = XMQuaternionMultiply(RotationQuaternion, XMQuaternionRotationRollPitchYaw(DeltaAngles.z, 0.f, -DeltaAngles.x)); 

    // performing rotation of y-axis (yaw) round world axis 
    XMMATRIX MRotation = XMMatrixMultiply(XMMatrixRotationQuaternion(RotationQuaternion), XMMatrixRotationRollPitchYaw(0.f, -DeltaAngles.y, 0.f)); 

    // keep track of rotation round y-axis because it is rotated round world axis 
    DeltaAngles = { 0.f, DeltaAngles.y, 0.f }; 

    // generating camera axis 
    XMFLOAT3 CameraAt, CameraRight, CameraUp; 
    XMStoreFloat3(&CameraAt, XMVector3TransformCoord(XMLoadFloat3(&OriginalAt), MRotation)); 
    XMStoreFloat3(&CameraRight, XMVector3TransformCoord(XMLoadFloat3(&OriginalRight), MRotation)); 
    XMStoreFloat3(&CameraUp, XMVector3TransformCoord(XMLoadFloat3(&OriginalUp), MRotation)); 

    // performing translation 
    Pos += CameraAt * DeltaPos.x; 
    Pos += CameraUp * DeltaPos.y; 
    Pos += CameraRight * DeltaPos.z; 
    DeltaPos = { 0.f, 0.f, 0.f }; 

    CameraAt += Pos; 

    if (At) 
     *At = CameraAt; 
    if (Up) 
     *Up = CameraUp; 

    // finally generate view matrix 
    DirectX::XMFLOAT4X4 Camera; 
    DirectX::XMStoreFloat4x4(&Camera, DirectX::XMMatrixLookAtLH(DirectX::XMLoadFloat3(&Pos), DirectX::XMLoadFloat3(&CameraAt), DirectX::XMLoadFloat3(&CameraUp))); 
    return Camera; 
} 
関連する問題