Перевод в мировые координаты

У меня есть координаты мыши: 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;
    }

Выходной луч:Перевод в мировые координаты

Вы возвращаете mouseDir1 вместо mouseDir2, который вы использовали для хранения результата вектора.

AxelH 15.05.2018 15:28

@AxelH Я знаю. Проблема не в этом.

Санаев 15.05.2018 15:30

В чем ценность pMatrix?

AxelH 15.05.2018 15:33

@AxelH Matrix4f p = новый Matrix4f (). Перспектива ((float) Math.toRadians (60.0f), 640f / 640f, 0.01f, 1000.0f); частный FloatBuffer pMatrix = BufferUtils.createFloatBuffer (16);

Санаев 15.05.2018 15:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
4
333
2

Ответы 2

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

Итак, я хочу сосредоточиться на фоне:

Why are the coordinates x, y the same?

Координаты одинаковы, потому что координаты 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;



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

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

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

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

Kai Burjack 15.05.2018 20:58

@ Rabbid76 Я бы не хотел, чтобы вы удаляли свой ответ, потому что я считаю его отличным, поскольку он объясняет предысторию.

Kai Burjack 15.05.2018 21:18

Библиотека матриц, которую вы, кажется, используете, 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-

Все время в центре отображается

Санаев 15.05.2018 22:23

«Все время в центре отображается» - что?

Kai Burjack 15.05.2018 22:36

Луч находится в центре.

Санаев 15.05.2018 22:37

Другие вопросы по теме