Перевод в мировые координаты - PullRequest
0 голосов
/ 15 мая 2018

У меня есть координаты мыши: mousePos, матричное представление view и матрица перспективной проекции pMatrix.

Я перевожу координаты в мир: я нахожу матрицу обратной проекции и вид обратной матрицы и умножаю на координаты мыши. Координаты начала координат z = 4, координаты конца z = -100.

В первом случае я получаю координаты mouseDir1 = (-0.1985 0.02887 4), а во втором случае mouseDir2 = (-0.1985 0.02887 -100).

Почему координаты x, y совпадают?

private Vector3f getCoord(MouseInput mouseInput,float z){
        int wdwWitdh = 640;
        int wdwHeight =640;

        Vector2d mousePos = mouseInput.getCurrentPos();
        float x = (float)(2 * mousePos.x) / (float)wdwWitdh - 1.0f;
        float y = 1.0f - (float)(2 * mousePos.y) / (float)wdwHeight;

        Matrix4f invProjectionMatrix = new Matrix4f();
        invProjectionMatrix.set(pMatrix);
        invProjectionMatrix.invert();
        Vector4f tmpVec = new Vector4f();
        tmpVec.set(x, y, z, 0);
        tmpVec.mul(invProjectionMatrix);
        tmpVec.z = z;
        tmpVec.w = 0.0f;

        Matrix4f viewMatrix = new Matrix4f().set(view);
        Matrix4f invViewMatrix = new Matrix4f();
        invViewMatrix.set(viewMatrix);
        invViewMatrix.invert();
        tmpVec.mul(invViewMatrix);
        Vector3f mouseDir1 = new Vector3f();
        mouseDir1.set(tmpVec.x, tmpVec.y, tmpVec.z);

        ///ТЕСТОВАЯ ПРОВЕРКА Z=-100;
        //конеч координаты луча
        Vector4f tmpVec1 = new Vector4f();
        tmpVec1.set(x, y, -100, 1.0f);
        tmpVec1.mul(invProjectionMatrix);
        tmpVec1.z =-100f;
        tmpVec1.w = 0.0f;
        tmpVec1.mul(invViewMatrix);
        Vector3f mouseDir2 = new Vector3f();
        mouseDir2.set(tmpVec1.x, tmpVec1.y, tmpVec1.z);
        System.out.println();
        return mouseDir1;
    }

Выходной луч: enter image description here

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Библиотека матриц, которую вы, похоже, используете, JOML, предоставляет эту операцию (которую обычно называют «не проектирующей») с помощью следующего кода (адаптированного к вашему коду):

Vector3f worldCoords = new Matrix4f(pMatrix).mul(view).unproject(x, y, z, 
  new int[] { 0, 0, wdwWidth, wdwHeight }, new Vector3f());

JavaDoc: https://joml -ci.github.io / JOML / apidocs / org / joml / Matrix4f.html # unproject-float-float-float-int: A-org.joml.Vector3f-

0 голосов
/ 15 мая 2018

В общем, вы должны использовать Matrix4f.unproject, так как @httpdigest продемонстрировал в своем ответе.

Поэтому я хочу сосредоточиться на фоне:

Почему координаты x, y одинаковы?

Координаты одинаковы, потому что координаты x и y источника одинаковы, и вы не делите перспективное деление послеумножение на матрицу обратной проекции.Операция mul не выполняет деления перспективы, она преобразует Vector4f на Matrix4f, и в результате получается также тип Vector4f.

Далее, исходные координаты, которые вы умножаете наМатрица обратной проекции должна быть нормализована координатами устройства, где x, y и z находятся в диапазоне [-1.0, 1.0].z=-1.0 - минимальная глубина (ближняя плоскость), а z=1.0 - максимальная глубина (дальняя плоскость).

Примечание: проекция линии визирования (луча обзора) на область просмотра, конечно, является точкой.

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

// transform x and y mouse coordinate to normalized device space 
Vector2d mousePos = mouseInput.getCurrentPos();
float x = (float)(2 * mousePos.x) / (float)wdwWitdh - 1.0f;
float y = 1.0f - (float)(2 * mousePos.y) / (float)wdwHeight;

....

// normalized device coordinate to view space coordinate (near plane)
Vector4f tmpVec = new Vector4f();
tmpVec.set(x, y, -1.0f, 1.0f);
tmpVec.mul(invProjectionMatrix);

// perspective divide
tmpVec.x = tmpVec.x / tmpVec.w;
tmpVec.y = tmpVec.y / tmpVec.w;
tmpVec.z = tmpVec.z / tmpVec.w;
tmpVec.w = 1.0;

// normalized device coordinate to view space coordinate (far plane)
Vector4f tmpVec1 = new Vector4f();
tmpVec1.set(x, y, 1.0f, 1.0f);
tmpVec1.mul(invProjectionMatrix);

// perspective divide
tmpVec1.x = tmpVec1.x / tmpVec1.w;
tmpVec1.y = tmpVec1.y / tmpVec1.w;
tmpVec1.z = tmpVec1.z / tmpVec1.w;
tmpVec1.w = 1.0;


Матрица проекции описывает отображение от 3D точек сцены к 2D точкам области просмотра.Матрица проекции преобразуется из пространства просмотра в пространство клипа.Координаты в пространстве клипа преобразуются в нормализованные координаты устройства (NDC) в диапазоне (-1, -1, -1) в (1, 1, 1) путем деления на w компонент координат клипа.

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

enter image description here

Из-за этого координаты x и y в окне просмотра зависят от глубины (координата пространства z).

...