Изо всех сил, чтобы мышь выбрать точку / четверку. Я считаю, что я либо использую координаты в неправильном пространстве, либо, возможно, не учитываю позицию / размер кадрового буфера (это подокно главного окна).
Попытка преобразования в различные координатные пространства и инвертирование модельной матрицы. В настоящее время проецируем луч в мировое пространство (надеюсь, правильно) и пытаемся сравнить его с местоположением точки (четырехугольника). Точка указана в локальном пространстве, но сущность отображается в начале координат (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)