Quaternion camera. How do I make it rotate correctly?

后端 未结 2 1749
臣服心动
臣服心动 2021-02-09 02:46

I have a 3D camera with its current rotation stored as a quaternion, and I\'m having trouble rotating it correctly. I want the camera to rotate incrementally around its local ax

相关标签:
2条回答
  • 2021-02-09 03:26

    Figured out the problem. For a mouse-controled first-person camera like the one I'm going for, I want to rotate around the local x-axis to look up and down, but the global y-axis for looking side to side.

    So this is correct for the x-axis:

    m_rot = m_rot * q;
    

    But I need to do this for the y-axis:

    m_rot = d * m_rot;
    
    0 讨论(0)
  • 2021-02-09 03:40

    Because I could not find any working example how to set up a first person camera using DirectXMath and because I spent two days working on my solution I decided to post my solution here. Perhaps there is anyone who is working on the same problem. My solution is not that optimized but the math behind it should be correct.

    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;
    }
    
    0 讨论(0)
提交回复
热议问题