Ручное вычисление луча выбора луча мыши в проблеме вращения Java

У меня проблемы с завершением алгоритма выбора лучей мыши для игры, которую я создаю с использованием java (и opengl / lwjgl). Я реализовал трассировку лучей, вдохновившись здесь и здесь. Я следил за книгой lwjgl по реализации игры. Следующий код представляет собой алгоритм выбора луча мыши:

// Calculate the normalized device coordinates
Vector2d mouseCoords = mouseInput.getPositionVector();
mouseCoords.mul((float)2 / window.width(), (float)2 / window.height());           
Vector4f mouseNDS = new Vector4f((float)mouseCoords.x, (float)mouseCoords.y, -1f, 1f);     

// Calculate the ray in cam space 
Vector4f eyeRay = mouseNDS.mul(renderer.getTransformations().getProjectionMatrix().invert());
eyeRay = new Vector4f(eyeRay.x, eyeRay.y, eyeRay.z, 0f);

// Calculate the ray in world space
Vector4f worldRay4f = eyeRay.mul(renderer.getTransformations().getViewMatrix(camera).invert());
Vector3f worldRay = new Vector3f(worldRay4f.x, worldRay4f.y, -worldRay4f.z).normalize();    

В конце концов, я хочу пересечь его с земной плоскостью (y = 0). Вот мой код для этого:

float lambda = camera.getPos().dot(new Vector3f(0, 1f , 0)) / worldRay.dot(new Vector3f(0, 1f, 0));      

Vector3f ray_scaled = worldRay.mul(lambda);
Vector3f ground_vec = new Vector3f();
camera.getPos().sub(ray_scaled, ground_vec);

Этот код работает, только если камера указывает в отрицательном направлении y (т.е. прямо вниз), и продолжает работать, когда я применяю изменение положения. Однако, если я поверну камеру, код сломается, то есть вектор земли больше не заканчивается под положением мыши.

Подозреваю, что с инверсией viewMatrix камеры что-то не так. ViewMatrix рассчитывается по этому коду:

public Matrix4f getViewMatrix(Camera camera) {
        Vector3f cameraPos = camera.getPos();
        Vector3f rotation = camera.getRot();

        viewMatrix.identity();
        viewMatrix.rotate((float)Math.toRadians(rotation.x), new Vector3f(1, 0, 0))
                  .rotate((float)Math.toRadians(rotation.y), new Vector3f(0, 1, 0))
                  .rotate((float)Math.toRadians(rotation.z), new Vector3f(0, 0, 1));
        viewMatrix.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z);
        return viewMatrix;
}

Может кто-то указать мне верное направление?


person Joris    schedule 02.01.2020    source источник


Ответы (1)


Возникла проблема при установке мирового луча (worldRay). Компонент z не должен инвертироваться:

Vector3f worldRay = new Vector3f(worldRay4f.x, worldRay4f.y, -worldRay4f.z).normalize();

Vector3f worldRay = new Vector3f(worldRay4f.x, worldRay4f.y, worldRay4f.z).normalize();   

Если камера указывает в отрицательном направлении оси y, то составляющие x и z worldRay4f равны 0,0, и ошибка не заметна.


Начало координат окна находится вверху слева. В нормализованном пространстве устройства верхний левый угол равен (-1, 1), а нижний левый - (-1, -1). Таким образом, координата y должна быть перевернута при преобразовании координаты мыши в нормализованное пространство устройства:

Vector2d mouseCoords = mouseInput.getPositionVector();
Vector4f mouseNDS = new Vector4f(
    (float)mouseCoords.x * 2f / window.width() - 1f,
    1f - (float)mouseCoords.y * 2f / window.height(),
    -1f, 1f);   
person Rabbid76    schedule 02.01.2020
comment
Спасибо, это на самом деле звучит очень логично. Когда я удаляю это отрицание, вектор переворачивается по оси z, однако я посмотрел дальше и обнаружил, что мне нужно отрицать координату y нормализованных координат устройства следующим образом: `` Vector4f mouseNDS = new Vector4f ((float ) mouseCoords.x, - (float) mouseCoords.y, -1f, 1f); `` Теперь он работает для всех преобразований камеры! - person Joris; 02.01.2020
comment
@Joris Начало координат окна находится вверху слева. Минимум NDC находится внизу слева. Поэтому координату y нужно перевернуть. - person Rabbid76; 02.01.2020