2016-06-15 6 views
11

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

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

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

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

Vector resulting from unprojection originate in same location Как видно из приведенного выше изображения, все векторы, кажется, происходят из того же места. Если я изменяю представление и повторяю процесс, то появляется тот же шаблон, но с другим источником векторов.

Different perspective, different origin of the vectors

Вот фрагменты кода, которые я использую, чтобы придумать с этим. Прежде всего я получаю позицию курсора, используя приведенный ниже код и передать его в мой метод «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, чтобы определить, попал ли треугольник. Я опустил код в приведенном выше фрагменте, потому что он не имеет отношения к этой проблеме.

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

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

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

    XMFLOAT4X4 viewMatrix; 

    // Keep camera's 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; 
} 

Он находится под влиянием двух методов, которые вращают камеру вокруг оси х-и у-осей камеры:

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)); 
} 

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

Edit 1:

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

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

Любой, кто может помочь и хочет помочь?

+3

Я не знаком с аргументом, но, как я увидел в «XMVectorSet (screenX, screenY, 5.0f, 0.0f)», вы использовали 4D-вектор. Таким образом, вы работаете в 4D-пространстве, и то, что вы видите, является его 2D-проекцией. Я правильно понимаю или нет? –

+3

См. Это возможно: http://stackoverflow.com/a/26662222/1306012 –

+3

Я фактически использую 3D-векторы, четвертая часть (0.0f) координат просто означает, что это вектор. Установка его в 1.0f означает, что это точка. – ackh

ответ

0

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

enter image description here

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

То, что я в конце концов сделал, чтобы решить обе проблемы является:

  1. Транспонирование матрицы перед передачей их XMVector3Unproject (уже описано выше)
  2. Транспозиция мой вид матрицы путем изменения кода метода SetViewMatrix (код смотри ниже)

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

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

    XMFLOAT4X4 viewMatrix; 

    // Keep camera's 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; 
}; 

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

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

4

Я использовал XMMatrixLookAtRH API в 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)) 
     ); 

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

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

6

Спасибо за ваш намек, Капил. Я попробовал метод 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 по адресу this.

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

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

3

Я смог получить одинаковые значения 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's 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().

Нет необходимости Транспонирование

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

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

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

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

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

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

+2

@ackh, Обратите внимание, что в опубликованном коде я также установил положение камеры как 1,1,1,1, то есть вне источника. Даже тогда я получаю правильные значения вектора экрана. Единственная проблема заключается в том, что я все еще не способен визуализировать вывод, кроме проверки векторных значений в отладчике Visual Studio. Я построил векторы с этими значениями на бумаге, и они выглядят правильно. Пожалуйста, проверьте свое графическое приложение. –

+1

Большое спасибо за ваши усилия здесь. Я попробую то, что вы предложили, и сообщите еще раз. К сожалению, это побочный проект, и это займет некоторое время, пока я не смогу вернуться к нему. – ackh