首页 > 解决方案 > Directx3D 11 构建带有旋转和平移的世界矩阵

问题描述

我想使用 wasd 来控制场景中的汽车移动。使用ws前后移动,a旋转d移动方向和小车方向。现在我可以使用 w 和 s 成功地向前和向后移动,并使用 a 和 d 来旋转我的车。但是,如果我同时按下 w 和 a,汽车只会在它的位置旋转,不再向前移动。

有谁知道错误在哪里?

#include "Car.h"


Car::Car() 
{
    
}

Car::~Car() 
{
    if (mModel) {
        delete mModel;
        mModel = nullptr;
    }

    // if (mCamera) {
    //     delete mCamera;
    //     mCamera = nullptr;
    // }
}

void Car::init(std::string modelPath) 
{
    mModel = new Model();
    mModel->load(modelPath);

    // mCamera = new Camera();
    // mCamera->setPosition({ mPosition.x, mPosition.y, mPosition.z });
}

void Car::setPosition(XMFLOAT3& pos) 
{
    mPosition = pos;

    // mCamera->setPosition({ mPosition.x, mPosition.y + 5, mPosition.z });
}

void Car::setProjection(XMMATRIX& proj) 
{
    mProjection = proj;
}

void Car::setView(XMMATRIX& view) 
{
    mView = view;
}

void Car::setPSConstantBuffer(PSConstantBuffer data) 
{
    mPSConstantData = data;
}

void Car::rebuildRUL()
{
    XMVECTOR R = XMLoadFloat3(&mRight);
    XMVECTOR U = XMLoadFloat3(&mUp);
    XMVECTOR L = XMLoadFloat3(&mLook);

    L = XMVector3Normalize(L);
    U = XMVector3Normalize(XMVector3Cross(L, R));

    R = XMVector3Cross(U, L);

    XMStoreFloat3(&mRight, R);
    XMStoreFloat3(&mUp, U);
    XMStoreFloat3(&mLook, L);
}

void Car::update(float deltaTime) 
{
    // mSpeed += mAcceleration * deltaTime;

    // walk(mSpeed * deltaTime * 0.0001f);

    // mCamera->updateView();
    // if (mMove) {
        rebuildRUL();

        // std::cout << mPosition.x << ", " << mPosition.y << ", " << mPosition.z << std::endl;

        mWorld = mRotation * XMMatrixTranslation(mPosition.x, mPosition.y + 1, mPosition.z);

        // mMove = false;
    // }
}

void Car::walk(float distance) 
{
    // std::cout << "distance: " << distance << std::endl;

    XMVECTOR s = XMVectorReplicate(distance);
    XMVECTOR look = XMLoadFloat3(&mLook);
    XMVECTOR pos = XMLoadFloat3(&mPosition);

    XMStoreFloat3(&mPosition, XMVectorMultiplyAdd(s, look, pos));
    // rebuildRUL();
}

void Car::strafe(float distance) 
{
    // std::cout << "strafe: " << distance << std::endl;
    
    XMVECTOR s = XMVectorReplicate(distance);
    XMVECTOR right = XMLoadFloat3(&mRight);
    XMVECTOR pos = XMLoadFloat3(&mPosition);

    XMStoreFloat3(&mPosition, XMVectorMultiplyAdd(s, right, pos));
    // rebuildRUL();
}

void Car::turn(float angle) 
{
    std::cout << "angle: " << angle << std::endl;

    static float totalAngle = 0.0f;
    totalAngle += angle;

    // if (totalAngle > 3.1410f / 4.0f) {
    //     totalAngle = 0.0f;
    // }

    XMMATRIX rot = XMMatrixRotationY(totalAngle);
    mRotation = rot;

    XMStoreFloat3(&mRight, XMVector3TransformNormal(XMLoadFloat3(&mRight), rot));
    XMStoreFloat3(&mUp, XMVector3TransformNormal(XMLoadFloat3(&mUp), rot));
    XMStoreFloat3(&mLook, XMVector3TransformNormal(XMLoadFloat3(&mLook), rot));

    // rebuildRUL();
    // strafe(angle);
}

void Car::draw() 
{
    mModel->updateMVP(
        XMMatrixTranspose(mWorld),
        XMMatrixTranspose(mView),
        XMMatrixTranspose(mProjection)
    );

    mModel->updatePSConstantBuffer(mPSConstantData);

    mModel->render();
}

void Car::processKeyboard(const bool* key_state, float delta) 
{
    if (key_state[VK_SHIFT]) {
        mWalkSpeed = 20.0f;
    } else {
        mWalkSpeed = 1.0f;
    }

    if (key_state[VK_UP] || key_state[0x57]) {
        walk(mWalkSpeed * delta * 0.005f);
        // mAcceleration = 1.0f;
    } else if (key_state[VK_DOWN] || key_state[0x53]) {
        // mAcceleration = -1.0f;
        walk(-mWalkSpeed * delta * 0.005f);
    } else {
        mAcceleration = 0;
    }

    if (key_state[VK_LEFT] || key_state[0x41]) {
        // mRotation = - 10.0f;
        turn(-mWalkSpeed * delta * 0.005f);
    } else if (key_state[VK_RIGHT] || key_state[0x44]) {
        // mRotation = 10.0f;
        turn(mWalkSpeed * delta * 0.005f);
    } else {
        // turn(0);
    }
}

void Car::processMouse(WPARAM btnState, int x, int y) 
{
    
}

标签: directx-11directxmath

解决方案


推荐阅读