Невозможно выбрать мышью квад, визуализированный в кадровом буфере - PullRequest
1 голос
/ 23 июня 2019

Изо всех сил, чтобы мышь выбрать точку / четверку. Я считаю, что я либо использую координаты в неправильном пространстве, либо, возможно, не учитываю позицию / размер кадрового буфера (это подокно главного окна).

Попытка преобразования в различные координатные пространства и инвертирование модельной матрицы. В настоящее время проецируем луч в мировое пространство (надеюсь, правильно) и пытаемся сравнить его с местоположением точки (четырехугольника). Точка указана в локальном пространстве, но сущность отображается в начале координат (0f, 0f, 0f), поэтому я не думаю, что она должна быть иной в мировом пространстве?

Чтобы получить луч мыши в мировом пространстве:

private fun calculateRay(): Vector3f {
        val mousePosition = Mouse.getCursorPosition()
        val ndc = toDevice(mousePosition)
        val clip = Vector4f(ndc.x, ndc.y, -1f, 1f)
        val eye = toEye(clip)
        return toWorld(eye)
    }

private fun toDevice(mousePosition: Vector2f): Vector2f {
        mousePosition.x -= fbo.x // Correct thing to do?
        mousePosition.y -= fbo.y
        val x = (2f * mousePosition.x) / fboSize.x - 1
        val y = (2f * mousePosition.y) / fboSize.y - 1
        return Vector2f(x, y)
    }

private fun toEye(clip: Vector4f): Vector4f {
        val invertedProjection = Matrix4f(projectionMatrix).invert()
        val eye = invertedProjection.transform(clip)
        return Vector4f(eye.x, eye.y, -1f, 0f)
    }

    private fun toWorld(eye: Vector4f): Vector3f {
        val viewMatrix = Maths.createViewMatrix(camera)
        val invertedView = Matrix4f(viewMatrix).invert()
        val world = invertedView.transform(eye)
        return Vector3f(world.x, world.y, world.z).normalize()
    }

При наведении на точку (11,25, -0,75) координаты луча равны (0,32847548, 0,05527423). Я попытался нормализовать позицию точки, и она все еще не совпадает.

Чувствую, что я что-то упускаю / пропускаю или просто неправильно манипулирую системами координат. Любое понимание будет высоко ценится, спасибо.

РЕДАКТИРОВАТЬ с дополнительной информацией:

Вершины четырехугольника: (-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f)

Загрузка матриц в шейдер:

private fun loadMatrices(position: Vector3f, rotation: Float, scale: Float, viewMatrix: Matrix4f, currentRay: Vector3f) {
        val modelMatrix = Matrix4f()
        modelMatrix.translate(position)
        modelMatrix.m00(viewMatrix.m00())
        modelMatrix.m01(viewMatrix.m10())
        modelMatrix.m02(viewMatrix.m20())
        modelMatrix.m10(viewMatrix.m01())
        modelMatrix.m11(viewMatrix.m11())
        modelMatrix.m12(viewMatrix.m21())
        modelMatrix.m20(viewMatrix.m02())
        modelMatrix.m21(viewMatrix.m12())
        modelMatrix.m22(viewMatrix.m22())
        modelMatrix.rotate(Math.toRadians(rotation.toDouble()).toFloat(), Vector3f(0f, 0f, 1f))
        modelMatrix.scale(scale)
        shader.loadModelViewMatrix(viewMatrix.mul(modelMatrix))
        shader.loadProjectionMatrix(projectionMatrix)
    }

Расчет gl_Position в вершинном шейдере:

gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 0.0, 1.0);

РЕДАКТИРОВАТЬ 2: изменил мой код после прочтения некоторых материалов на основе комментариев Раббида. Не уверен, что мне потребуется деление на 2 в размере области просмотра (у меня дисплей MacBook с сетчаткой).

mousePosition.sub(fboPosition)
        val w = (fboSize.x / 2).toInt()
        val h = (fboSize.y / 2).toInt()
        val y = h - mousePosition.y

        val viewMatrix = Maths.createViewMatrix(camera)
        val origin = Vector3f()
        val dir = Vector3f()
        Matrix4f(projectionMatrix).mul(viewMatrix)
                                  .unprojectRay(mousePosition.x, y, intArrayOf(0, 0, w, h), origin, dir)

1 Ответ

2 голосов
/ 24 июня 2019

Верхнее левое начало окна окна (0,0).Поэтому, если вы получите (0, 0), если мышь находится в верхнем левом углу окна, вы должны пропустить:

mousePosition.x -= fbo.x // Correct thing to do?
mousePosition.y -= fbo.y

, так как нижний левый угол кадрового буфера равен (0,0), координата y должна быть перевернута:

val y = 1 - (2f * mousePosition.y) / fboSize.y

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

val eye = invertedProjection.transform(clip)
return Vector3f(eye.x/eye.w, eye.y/eye.w, eye.z/eye.w)
...