Неожиданный результат при непроектировании координат экрана в DirectX

Чтобы определить, щелкнул ли пользователь какой-либо из моих 3D-объектов, я пытаюсь превратить координаты экрана щелчка в вектор, который затем я использую, чтобы проверить, попал ли какой-либо из моих треугольников. Для этого я использую метод XMVector3Unproject, предоставляемый DirectX и Im, реализующий все в С++/CX.

Проблема, с которой сталкивается Im, заключается в том, что вектор, являющийся результатом непроектирования экранных координат, вовсе не таков, как я ожидаю. На следующем рисунке показано следующее:

Вектор, полученный в результате непроекции Позиция курсора во время щелчка (выделено желтым цветом) видна в изометрическом виде слева. Как только я нажимаю, вектор, полученный в результате непроектирования, появляется за моделью, обозначенной на изображениях, как белая линия, проникающая в модель. Поэтому вместо того, чтобы происходить в месте расположения курсора и идти в экран в изометрическом виде, он появляется в совершенно другом положении.

Когда я перемещаю мышь в изометрическом представлении по горизонтали, пока нажимаем, а затем перемещаем мышь по вертикали и нажимаем на рисунок ниже. Все строки на двух изображениях представляют собой векторы, возникающие при нажатии. Модель была удалена для лучшей видимости.

Вектор, вызванный непроектированием, происходит в том же месте Таким образом, как видно из приведенного выше изображения, все векторы, по-видимому, происходят из одного и того же местоположения. Если я изменяю представление и повторяю процесс, то появляется тот же шаблон, но с другим источником векторов.

Другая перспектива, различное происхождение векторов

Вот фрагменты кода, которые я использую, чтобы придумать это. Прежде всего, я получаю позицию курсора, используя приведенный ниже код, и передаю его методу "SelectObject" вместе с шириной и высотой области рисования:

void Demo::OnPointerPressed(Object^ sender, PointerEventArgs^ e)
{
  Point currentPosition = e->CurrentPoint->Position;

  if(m_model->SelectObject(currentPosition.X, currentPosition.Y, m_renderTargetWidth, m_renderTargetHeight))
  {
    m_RefreshImage = true;
  }
}

Метод "SelectObject" выглядит следующим образом:

bool Model::SelectObject(float screenX, float screenY, float screenWidth, float screenHeight)
{
  XMMATRIX projectionMatrix = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->projection);
  XMMATRIX viewMatrix       = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->view);
  XMMATRIX modelMatrix      = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->model);

  XMVECTOR v = XMVector3Unproject(XMVectorSet(screenX, screenY, 5.0f, 0.0f),
                                  0.0f,
                                  0.0f,
                                  screenWidth,
                                  screenHeight,
                                  0.0f,
                                  1.0f,
                                  projectionMatrix,
                                  viewMatrix,
                                  modelMatrix);

  XMVECTOR rayOrigin = XMVector3Unproject(XMVectorSet(screenX, screenY, 0.0f, 0.0f),
                                          0.0f,
                                          0.0f,
                                          screenWidth,
                                          screenHeight,
                                          0.0f,
                                          1.0f,
                                          projectionMatrix,
                                          viewMatrix,
                                          modelMatrix);

  // Code to retrieve v0, v1 and v2 is omitted

  if(Intersects(rayOrigin, XMVector3Normalize(v - rayOrigin), v0, v1, v2, depth))
  {
    return true;
  }
}

В конечном итоге вычисляемый вектор используется методом Intersects пространства имен DirectX:: TriangleTests, чтобы определить, попал ли треугольник. Ive опустил код в приведенном выше фрагменте, потому что он не имеет отношения к этой проблеме.

Для рендеринга этих изображений я использую матрицу ортографических проекций и камеру, которая может вращаться вокруг своей локальной оси x и y, которая генерирует матрицу вида. Мировая матрица всегда остается прежней, т.е. Является просто единичной матрицей.

Матрица представления вычисляется следующим образом (на основе примера в программе программирования 3D Фрэнк Лунас):

void Camera::SetViewMatrix()
{
  XMFLOAT3 cameraPosition;
  XMFLOAT3 cameraXAxis;
  XMFLOAT3 cameraYAxis;
  XMFLOAT3 cameraZAxis;

  XMFLOAT4X4 viewMatrix;

  // Keep camera axes orthogonal to each other and of unit length.
  m_cameraZAxis = XMVector3Normalize(m_cameraZAxis);
  m_cameraYAxis = XMVector3Normalize(XMVector3Cross(m_cameraZAxis, m_cameraXAxis));

  // m_cameraYAxis and m_cameraZAxis are already normalized, so there is no need
  // to normalize the below cross product of the two.
  m_cameraXAxis = XMVector3Cross(m_cameraYAxis, m_cameraZAxis);

  // Fill in the view matrix entries.
  float x = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraXAxis));
  float y = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraYAxis));
  float z = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraZAxis));

  XMStoreFloat3(&cameraPosition, m_cameraPosition);
  XMStoreFloat3(&cameraXAxis   , m_cameraXAxis);
  XMStoreFloat3(&cameraYAxis   , m_cameraYAxis);
  XMStoreFloat3(&cameraZAxis   , m_cameraZAxis);

  viewMatrix(0, 0) = cameraXAxis.x;
  viewMatrix(1, 0) = cameraXAxis.y;
  viewMatrix(2, 0) = cameraXAxis.z;
  viewMatrix(3, 0) = x;

  viewMatrix(0, 1) = cameraYAxis.x;
  viewMatrix(1, 1) = cameraYAxis.y;
  viewMatrix(2, 1) = cameraYAxis.z;
  viewMatrix(3, 1) = y;

  viewMatrix(0, 2) = cameraZAxis.x;
  viewMatrix(1, 2) = cameraZAxis.y;
  viewMatrix(2, 2) = cameraZAxis.z;
  viewMatrix(3, 2) = z;

  viewMatrix(0, 3) = 0.0f;
  viewMatrix(1, 3) = 0.0f;
  viewMatrix(2, 3) = 0.0f;
  viewMatrix(3, 3) = 1.0f;

  m_modelViewProjectionConstantBufferData->view = viewMatrix;
}

На него влияют два метода, которые поворачивают камеру вокруг оси x и y камеры:

void Camera::ChangeCameraPitch(float angle)
{
  XMMATRIX rotationMatrix = XMMatrixRotationAxis(m_cameraXAxis, angle);

  m_cameraYAxis = XMVector3TransformNormal(m_cameraYAxis, rotationMatrix);
  m_cameraZAxis = XMVector3TransformNormal(m_cameraZAxis, rotationMatrix);
}

void Camera::ChangeCameraYaw(float angle)
{
  XMMATRIX rotationMatrix = XMMatrixRotationAxis(m_cameraYAxis, angle);

  m_cameraXAxis = XMVector3TransformNormal(m_cameraXAxis, rotationMatrix);
  m_cameraZAxis = XMVector3TransformNormal(m_cameraZAxis, rotationMatrix);
}

Матрица мира/модели и матрица проекции вычисляются следующим образом:

void Model::SetProjectionMatrix(float width, float height, float nearZ, float farZ)
{
  XMMATRIX orthographicProjectionMatrix = XMMatrixOrthographicRH(width, height, nearZ, farZ);

  XMFLOAT4X4 orientation = XMFLOAT4X4
  (
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f
  );

  XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);

  XMStoreFloat4x4(&m_modelViewProjectionConstantBufferData->projection, XMMatrixTranspose(orthographicProjectionMatrix * orientationMatrix));
}

void Model::SetModelMatrix()
{
  XMFLOAT4X4 orientation = XMFLOAT4X4
  (
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f
  );

  XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);

  XMStoreFloat4x4(&m_modelViewProjectionConstantBufferData->model, XMMatrixTranspose(orientationMatrix));
}

Честно говоря, я еще не понимаю проблему, с которой сталкивается Im. Id быть благодарным, если кто-либо с более глубоким пониманием может дать мне некоторые подсказки относительно того, где мне нужно применить изменения, чтобы вектор, вычисленный из непроектирования, начинался с позиции курсора и перемещался в экран.

Изменить 1:

Я предполагаю, что это связано с тем, что моя камера находится в (0, 0, 0) в мировых координатах. Камера вращается вокруг своей локальной оси x и y. Из того, что я понимаю, матрица вида, созданная камерой, строит плоскость, на которой проецируется изображение. Если это так, то это объясняет, почему луч находится в каком-то "неожиданном" месте.

Мое предположение заключается в том, что мне нужно переместить камеру из центра так, чтобы она находилась вне объекта. Однако, если просто изменить переменную-член m_cameraPosition камеры, моя модель полностью искажается.

Кто-нибудь может и хочет помочь?

Ответ 1

Как уже упоминалось, проблема не была полностью решена, хотя щелчок теперь работает. Проблема с искажением модели при перемещении камеры, о которой я подозревал, все еще присутствует. То, что я имел в виду с "искажением модели", видно на следующей иллюстрации:

введите описание изображения здесь

Левое изображение показывает, как выглядит модель, когда камера расположена в центре мира, то есть (0, 0, 0), а на правом изображении показано, что происходит, когда я перемещаю камеру в направлении отрицательной оси y. Как видно, модель расширяется снизу и становится меньше в верхней части, что является тем же самым поведением, описанным в ссылке которую я уже предоставил выше.

В конце концов я решил решить обе проблемы:

  • Переместите матрицы перед передачей их в проект XMVector3Un (уже описанный выше)
  • Перестроена моя матрица просмотра, изменив код метода SetViewMatrix (код ниже)

Теперь метод SetViewMatrix выглядит следующим образом:

void Camera::SetViewMatrix()
{
  XMFLOAT3 cameraPosition;
  XMFLOAT3 cameraXAxis;
  XMFLOAT3 cameraYAxis;
  XMFLOAT3 cameraZAxis;

  XMFLOAT4X4 viewMatrix;

  // Keep camera axes orthogonal to each other and of unit length.
  m_cameraZAxis = XMVector3Normalize(m_cameraZAxis);
  m_cameraYAxis = XMVector3Normalize(XMVector3Cross(m_cameraZAxis, m_cameraXAxis));

  // m_cameraYAxis and m_cameraZAxis are already normalized, so there is no need
  // to normalize the below cross product of the two.
  m_cameraXAxis = XMVector3Cross(m_cameraYAxis, m_cameraZAxis);

  // Fill in the view matrix entries.
  float x = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraXAxis));
  float y = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraYAxis));
  float z = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraZAxis));

  //XMStoreFloat3(&cameraPosition, m_cameraPosition);
  XMStoreFloat3(&cameraXAxis, m_cameraXAxis);
  XMStoreFloat3(&cameraYAxis, m_cameraYAxis);
  XMStoreFloat3(&cameraZAxis, m_cameraZAxis);

  viewMatrix(0, 0) = cameraXAxis.x;
  viewMatrix(0, 1) = cameraXAxis.y;
  viewMatrix(0, 2) = cameraXAxis.z;
  viewMatrix(0, 3) = x;

  viewMatrix(1, 0) = cameraYAxis.x;
  viewMatrix(1, 1) = cameraYAxis.y;
  viewMatrix(1, 2) = cameraYAxis.z;
  viewMatrix(1, 3) = y;

  viewMatrix(2, 0) = cameraZAxis.x;
  viewMatrix(2, 1) = cameraZAxis.y;
  viewMatrix(2, 2) = cameraZAxis.z;
  viewMatrix(2, 3) = z;

  viewMatrix(3, 0) = 0.0f;
  viewMatrix(3, 1) = 0.0f;
  viewMatrix(3, 2) = 0.0f;
  viewMatrix(3, 3) = 1.0f;

  m_modelViewProjectionConstantBufferData->view = viewMatrix;
}

Итак, я только что обменял координаты строк и столбцов. Обратите внимание, что я должен был убедиться, что мой метод ChangeCameraYaw вызывается до моего метода ChangeCameraPitch. Это необходимо, потому что ориентация модели в противном случае не так, как я хочу.

Существует и другой подход, который можно использовать. Вместо того, чтобы переносить матрицу представления, обменивая координаты строки и столбца и перенося ее перед передачей в XMVector3Unproject, я мог бы использовать ключевое слово row_major в вершинном шейдере вместе с матрицей вида:

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix model;
  row_major matrix view;
  matrix projection;
};

Я наткнулся на эту идею в этом блоге. Ключевое слово row_major влияет на то, как компилятор шейдера интерпретирует матрицу в памяти. То же самое можно было бы достичь, изменив порядок векторного умножения матрицы в вершинном шейдере, т.е. Используя pos = mul(view, pos); вместо pos = mul(pos, view);

Это в значительной степени. Эти две проблемы действительно взаимосвязаны, но, используя то, что я написал в этом вопросе, я смог решить обе проблемы, поэтому я принимаю свой ответ в качестве ответа на этот вопрос. Надеюсь, это поможет кому-то в будущем.

Ответ 2

Спасибо за ваш намек, Капил. Я попробовал метод XMMatrixLookAtRH, но не смог изменить шаг камеры/рыскание, используя этот подход, поэтому я отбросил этот подход и сам создал матрицу.

Решена моя проблема - переносить матрицы модели, представления и проекции с помощью XMMatrixTranspose, прежде чем передавать их в XMVector3Unproject. Поэтому вместо того, чтобы иметь следующий код

  XMMATRIX projectionMatrix = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->projection);
  XMMATRIX viewMatrix       = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->view);
  XMMATRIX modelMatrix      = XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->model);

  XMVECTOR rayBegin = XMVector3Unproject(XMVectorSet(screenX, screenY, -m_boundingSphereRadius, 0.0f),
                                         0.0f,
                                         0.0f,
                                         screenWidth,
                                         screenHeight,
                                         0.0f,
                                         1.0f,
                                         projectionMatrix,
                                         viewMatrix,
                                         modelMatrix);

он должен быть

  XMMATRIX projectionMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->projection));
  XMMATRIX viewMatrix       = XMMatrixTranspose(XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->view));
  XMMATRIX modelMatrix      = XMMatrixTranspose(XMLoadFloat4x4(&m_modelViewProjectionConstantBufferData->model));

  XMVECTOR rayBegin = XMVector3Unproject(XMVectorSet(screenX, screenY, -m_boundingSphereRadius, 0.0f),
                                         0.0f,
                                         0.0f,
                                         screenWidth,
                                         screenHeight,
                                         0.0f,
                                         1.0f,
                                         projectionMatrix,
                                         viewMatrix,
                                         modelMatrix);

Мне не совсем понятно, зачем мне переставлять матрицы, прежде чем передавать их методу unproject. Тем не менее, я подозреваю, что это связано с проблемой, с которой мне приходится сталкиваться, когда я перемещаю свою камеру. Эта проблема уже была описана здесь в StackOverflow .

Мне еще не удалось решить эту проблему. Простое преобразование матрицы просмотра не разрешает ее. Однако моя основная проблема решена, и моя модель, наконец, доступна для интерактивного использования.

Если у кого-нибудь есть что добавить и рассказать о том, почему матрицы необходимо переместить или почему перемещение камеры искажает модель, пожалуйста, продолжайте и публикуйте комментарии или ответы.

Ответ 3

Я использовал API XMMatrixLookAtRH в Model::SetViewMatrix() для вычисления матрицы вида и получил приличные значения векторов v и rayOrigin.

Например,

XMStoreFloat4x4(
        &m_modelViewProjectionConstantBufferData->view,
        XMMatrixLookAtRH(m_cameraPosition, XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), 
        XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f))
        );

Хотя я не смог визуализировать вывод на экране, я проверил результат, вычислив простые значения в консольном приложении, и векторные значения выглядят правильными. Пожалуйста, проверьте свое выражение и подтвердите его.

ПРИМЕЧАНИЕ.. Чтобы использовать API XMMatrixLookAtRH вместо текущего подхода, вам необходимо указать фокус и направление вверх.

Ответ 4

Я могу получить равные значения векторов v и rayOrigin, используя метод XMMatrixLookAtRH, а также вашу настраиваемую матрицу представлений с этим кодом без необходимости операции переноса матрицы:

#include <directxmath.h>

using namespace DirectX;

XMVECTOR m_cameraXAxis;
XMVECTOR m_cameraYAxis;
XMVECTOR m_cameraZAxis;
XMVECTOR m_cameraPosition;

XMMATRIX gView;
XMMATRIX gView2;
XMMATRIX gProj;
XMMATRIX gModel;

void SetViewMatrix()
{
    XMVECTOR lTarget = XMVectorSet(2.0f, 2.0f, 2.0f, 1.0f);

    m_cameraPosition = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f);
    m_cameraZAxis = XMVector3Normalize(XMVectorSubtract(m_cameraPosition, lTarget));
    m_cameraXAxis = XMVector3Normalize(XMVector3Cross(XMVectorSet(1.0f, -1.0f, -1.0f, 0.0f), m_cameraZAxis));

    XMFLOAT3 cameraPosition;
    XMFLOAT3 cameraXAxis;
    XMFLOAT3 cameraYAxis;
    XMFLOAT3 cameraZAxis;

    XMFLOAT4X4 viewMatrix;

    // Keep camera axes orthogonal to each other and of unit length.
    m_cameraZAxis = XMVector3Normalize(m_cameraZAxis);
    m_cameraYAxis = XMVector3Normalize(XMVector3Cross(m_cameraZAxis, m_cameraXAxis));

    // m_cameraYAxis and m_cameraZAxis are already normalized, so there is no need
    // to normalize the below cross product of the two.
    m_cameraXAxis = XMVector3Cross(m_cameraYAxis, m_cameraZAxis);

    // Fill in the view matrix entries.
    float x = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraXAxis));
    float y = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraYAxis));
    float z = -XMVectorGetX(XMVector3Dot(m_cameraPosition, m_cameraZAxis));

    XMStoreFloat3(&cameraPosition, m_cameraPosition);
    XMStoreFloat3(&cameraXAxis, m_cameraXAxis);
    XMStoreFloat3(&cameraYAxis, m_cameraYAxis);
    XMStoreFloat3(&cameraZAxis, m_cameraZAxis);

    viewMatrix(0, 0) = cameraXAxis.x;
    viewMatrix(1, 0) = cameraXAxis.y;
    viewMatrix(2, 0) = cameraXAxis.z;
    viewMatrix(3, 0) = x;

    viewMatrix(0, 1) = cameraYAxis.x;
    viewMatrix(1, 1) = cameraYAxis.y;
    viewMatrix(2, 1) = cameraYAxis.z;
    viewMatrix(3, 1) = y;

    viewMatrix(0, 2) = cameraZAxis.x;
    viewMatrix(1, 2) = cameraZAxis.y;
    viewMatrix(2, 2) = cameraZAxis.z;
    viewMatrix(3, 2) = z;

    viewMatrix(0, 3) = 0.0f;
    viewMatrix(1, 3) = 0.0f;
    viewMatrix(2, 3) = 0.0f;
    viewMatrix(3, 3) = 1.0f;

    gView = XMLoadFloat4x4(&viewMatrix);

    gView2 = XMMatrixLookAtRH(m_cameraPosition, XMVectorSet(2.0f, 2.0f, 2.0f, 1.0f),
            XMVectorSet(1.0f, -1.0f, -1.0f, 0.0f));

    //m_modelViewProjectionConstantBufferData->view = viewMatrix;
    printf("yo");
}

void SetProjectionMatrix(float width, float height, float nearZ, float farZ)
{
    XMMATRIX orthographicProjectionMatrix = XMMatrixOrthographicRH(width, height, nearZ, farZ);

    XMFLOAT4X4 orientation = XMFLOAT4X4
        (
            1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f
            );

    XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);

    gProj = XMMatrixTranspose( XMMatrixMultiply(orthographicProjectionMatrix, orientationMatrix));
}

void SetModelMatrix()
{
    XMFLOAT4X4 orientation = XMFLOAT4X4
        (
            1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f
            );

    XMMATRIX orientationMatrix = XMMatrixTranspose( XMLoadFloat4x4(&orientation));

    gModel = orientationMatrix;
}

bool SelectObject(float screenX, float screenY, float screenWidth, float screenHeight)
{
    XMMATRIX projectionMatrix = gProj;
    XMMATRIX viewMatrix = gView;
    XMMATRIX modelMatrix = gModel;
    XMMATRIX viewMatrix2 = gView2;

    XMVECTOR v = XMVector3Unproject(XMVectorSet(screenX, screenY, 5.0f, 0.0f),
        0.0f,
        0.0f,
        screenWidth,
        screenHeight,
        0.0f,
        1.0f,
        projectionMatrix,
        viewMatrix,
        modelMatrix);

    XMVECTOR rayOrigin = XMVector3Unproject(XMVectorSet(screenX, screenY, 0.0f, 0.0f),
        0.0f,
        0.0f,
        screenWidth,
        screenHeight,
        0.0f,
        1.0f,
        projectionMatrix,
        viewMatrix,
        modelMatrix);

    // Code to retrieve v0, v1 and v2 is omitted
    auto diff = v - rayOrigin;
    auto diffNorm = XMVector3Normalize(diff);

    XMVECTOR v2 = XMVector3Unproject(XMVectorSet(screenX, screenY, 5.0f, 0.0f),
        0.0f,
        0.0f,
        screenWidth,
        screenHeight,
        0.0f,
        1.0f,
        projectionMatrix,
        viewMatrix2,
        modelMatrix);

    XMVECTOR rayOrigin2 = XMVector3Unproject(XMVectorSet(screenX, screenY, 0.0f, 0.0f),
        0.0f,
        0.0f,
        screenWidth,
        screenHeight,
        0.0f,
        1.0f,
        projectionMatrix,
        viewMatrix2,
        modelMatrix);

    auto diff2 = v2 - rayOrigin2;
    auto diffNorm2 = XMVector3Normalize(diff2);

    printf("hi");
    return true;
}

int main()
{
    SetViewMatrix();
    SetProjectionMatrix(1000, 1000, 0.0f, 1.0f);
    SetModelMatrix();

    SelectObject(500, 500, 1000, 1000);

    return 0;
}

Пожалуйста, проверьте свою заявку с помощью этого кода и подтвердите. Вы увидите, что код совпадает с вашим предыдущим кодом. Единственным дополнением являются начальные значения параметров камеры, вычисление второй матрицы представления в SetViewMatrix() с использованием метода XMMatrixLookAtRH и вычисление векторов с использованием обеих матриц вида в SelectObject().

Не нужно транспонировать

Мне не пришлось транспонировать какую-либо матрицу. Транспонирование не требуется для матриц Проекция и Модель, потому что они являются диагональными матрицами и транспонирование их даст одну и ту же матрицу. Я не думаю, что требуется транспонирование матрицы View. Формула XMMatrixLookAtRH объяснила здесь, которая дает матрицу вида точно так же, как ваша. Кроме того, пример проекта, представленный здесь, не переносит его матрицы при проверке пересечения. Вы можете загрузить и проверить образец проекта.

Возможные источники проблем

1) Инициализация. Единственным кодом, который я не смог увидеть, является ваша инициализация параметров m_cameraZAxis, m_cameraXAxis, nearZ, farZ и т.д. Кроме того, я не использовал функции вращения камеры, Как вы можете видеть, я инициализировал камеру, используя векторы положения, цели и направления для вычисления. Проверьте, соответствует ли ваш первоначальный расчет m_cameraZAxis моим примером кода.

2) LH/RH посмотрите: убедитесь, что в вашем коде отсутствует случайный пуск левой и правой.

3) Убедитесь, что ваш код вращения (ChangeCameraPitch или ChangeCameraYaw) случайно создает оси камеры, которые не ортогональны. Вы используете камеру ось Y как входной сигнал в ChangeCameraYaw и как вывод в ChangeCameraPitch. Но ось Y составляет reset в SetViewMatrix поперечным продуктом или осей X и Z. Таким образом, более раннее значение оси Y может потеряться.

Удачи вам в применении! Скажите, находите ли вы правильное решение и причину своей проблемы.