ScreenToWorld или поиск вектора, на который была умножена матрица

Начинающий
Статус
Оффлайн
Регистрация
30 Янв 2018
Сообщения
79
Реакции[?]
6
Поинты[?]
0
Здравствуйте!
Пытаюсь написать функцию для конвертирования экранных координат в мировые с заданной глубиной, но все безуспешно.
Функция конвертирования мировых координат в экранные работает прекрасно.
Выяснил, что проблема в умножении матриц, а точнее - в поиске вектора на который она была умножена.
Подробнее:
A - проекция матрицы просмотра размером 4x4
B - вектор мировых координат размером 3, но для умножения на матрицу используется вектор размером 4, 4-ый элемент которого равен единице
C - результат умножения матрицы и вектора, размер 4x1. Это же и будет экранными координатами

A * B = C

Известны A и C, нужно вывести формулу, благодаря которой можно будет высчитать B.
B = C / A
Но так как делить матрицы нельзя, то заменяем деление на умножение на матрицу, обратную исходной. То есть:
B = C * Ai
Ai - матрица, обратная матрице A
Тут и появляется проблема. По правилам умножения матриц количество столбцов умножаемой матрицы должно равняться количеству строк матрицы, на которую производиться умножение, то есть 1 должно быть равно 4, что является ложью. Это значит что умножение C * Ai невозможно.
Как в таком случае найти исходный вектор B, как ищут мировые координаты, используя экранные?
Исходники функций ScreenToWorld написанных другими программистами смотрел, но почему то в моем случае это не работает.
C++:
void TestProcedure(D3DXVECTOR3 worldPosition) {
    D3DXVECTOR3 screenPosition;
    D3DXMATRIX m((float*)projViewMatrix);

    Log("World Position: [%f | %f | %f]", worldPosition.x, worldPosition.y, worldPosition.z);

    screenPosition.x = (m._11 * worldPosition.x) + (m._12 * worldPosition.y) + (m._13 * worldPosition.z) + m._14;
    screenPosition.y = (m._21 * worldPosition.x) + (m._22 * worldPosition.y) + (m._23 * worldPosition.z) + m._24;
    screenPosition.z = (m._31 * worldPosition.x) + (m._32 * worldPosition.y) + (m._33 * worldPosition.z) + m._34;

    Log("Screen Position: [%f | %f | %f]", screenPosition.x, screenPosition.y, screenPosition.z);

    D3DXMATRIX minv = {};
    D3DXMatrixInverse(&minv, 0, &m);
    D3DXMatrixTranspose(&minv, &minv);

    worldPosition.x = (screenPosition.x * minv._11) + (screenPosition.y * minv._21) + (screenPosition.z * minv._31) + minv._41;
    worldPosition.y = (screenPosition.x * minv._12) + (screenPosition.y * minv._22) + (screenPosition.z * minv._32) + minv._42;
    worldPosition.z = (screenPosition.x * minv._13) + (screenPosition.y * minv._23) + (screenPosition.z * minv._33) + minv._43;

    Log("World Position again: [%f | %f | %f]", worldPosition.x, worldPosition.y, worldPosition.z);
}
Так же написал тестовую функцию, которая умножает проекцию матрицы просмотра на вектор мировых координат, получая при этом экранные координаты(не приведенные к текущему разрешению экрана), а затем заново преобразовывает их в мировые координаты, которые должны быть равны изначально переданным в функцию, но это не так. Опробовал так же формулу, которая позволяет перемножить матрицы, транспонировав их обе - тоже не дала нужного результата.
При этом значения приблизительно похожи на нужные, но все же отличаются:
Код:
World Position: [0.000000 | 0.000000 | 2000.000000]
Screen Position: [-412.117828 | 45.904404 | 3439.193604]
World Position again: [0.435925 | 44.107887 | 1970.907349]
В функцию передаются координаты 0, 0, 2000, а на выходе ~0, 44, 1970. Так же изменял Z координаты с 2000 на 1000, и в результате получалось примерно 1000. Только почему есть такая погрешность?
Надеюсь на помощь знающих людей! Заранее спасибо!
 
Сверху Снизу