Как правильно использовать метод UnProject в OpenTK и получать мировые координаты от наведения мыши? - PullRequest
1 голос
/ 28 апреля 2019

Я пытаюсь получить мировые координаты, наведя указатель мыши на GLControl элемент управления, в котором отображается мир. Я нашел десятки примеров и решений, но я не могу с ними работать, я все еще учусьи не дошел до своей точки.Но я продолжал копать, нашел несколько примеров и выбрал тот, который одобрен его оригинальным автором, который работает с подобной конструкцией рендера, но все еще не работает для меня.

Я установил окно для вывода преобразованных координат.Я получаю x, y = 0 в центре контроля, что означает, что я, возможно, иду по правильному пути.Когда я перемещаю мышь вокруг осей x и y, она выдает правильные значения (например, чем выше мышь от центра элемента управления, тем выше y и т. Д.), Но только на уровне -1.65/1.65 Макс от центра.Не похоже, что он получает мою матрицу Modelview, потому что она должна отличаться в зависимости от eyeZ, чего нет.Изменение eyeZ не имеет никакого эффекта.Он по-прежнему действует так, как если бы я не «увеличивал / уменьшал».

Я настроил Projection, Modelview матрицы и Viewport так:

    GL.MatrixMode(MatrixMode.Projection)
    GL.LoadIdentity()

    GL.LoadMatrix(Matrix4.CreatePerspectiveFieldOfView(Math.PI / 4, glControl.Width / glControl.Height, 1.0F, 128.0F))

    GL.MatrixMode(MatrixMode.Modelview)
    GL.LoadIdentity()

    GL.LoadMatrix(Matrix4.LookAt(0F, 0F, zoom, 0F, 0F, 0F, 0F, 1.0F, 0F))

    GL.Viewport(0, 0, glControl.Width, glControl.Height)

Затем у меня есть эти две функции, которые вызываются, когда моя мышь перемещается над GLControl и передают координаты мыши.

Public Function screenToWorld(ByVal x As Integer, ByVal y As Integer) As Vector4
    Dim modelViewMatrix As Matrix4
    Dim projectionMatrix As Matrix4
    Dim viewport(4) As Integer

    GL.GetFloat(GetPName.ModelviewMatrix, modelViewMatrix)
    GL.GetFloat(GetPName.ProjectionMatrix, projectionMatrix)
    GL.GetInteger(GetPName.Viewport, viewport)

    Return UnProject(projectionMatrix, modelViewMatrix, New Size(viewport(2), viewport(3)), New Vector2(x, y))
End Function

Public Function UnProject(ByRef projection As Matrix4, ByVal view As Matrix4, ByVal viewport As Size, ByVal mouse As Vector2) As Vector4
    Dim vec As Vector4

    vec.X = 2.0F * mouse.X / viewport.Width - 1
    vec.Y = -(2.0F * mouse.Y / viewport.Height - 1)
    vec.Z = 0F
    vec.W = 1.0F

    Dim viewInv As Matrix4 = Matrix4.Invert(view)
    Dim projInv As Matrix4 = Matrix4.Invert(projection)

    Vector4.Transform(vec, projInv, vec)
    Vector4.Transform(vec, viewInv, vec)

    If vec.W > Single.Epsilon OrElse vec.W < Single.Epsilon Then
        vec.X /= vec.W
        vec.Y /= vec.W
        vec.Z /= vec.W
    End If

    Return vec
End Function

Также я воздерживаюсь от использования ортографической проекции.

...