如何在OpenTK中正确使用UnProject方法并从鼠标悬停获取世界坐标?

时间:2019-04-28 20:28:06

标签: vb.net opentk

我试图通过将鼠标悬停在渲染世界的GLControl控件上来获取世界坐标。我找到了许多示例和解决方案,但我无法使用它们,还在学习,还没有达到目的。但是我一直在挖掘,找到了一些示例,并选择了一个示例,该示例得到了其原始作者的认可,该示例可以使用类似的渲染构造,但似乎对我而言并不起作用。

我已经设置了一个窗口来输出转换后的坐标。我将x, y = 0置于控件的中心,这意味着我可能会走正确的路。当我在xy轴上移动鼠标时,它会输出适当的值(例如,鼠标距控件中心越高,y越高,等等),但只喜欢从中心到最大-1.65/1.65。它似乎并没有获得我的Modelview矩阵,因为它应该根据eyeZ而有所不同,而实际上并没有。更改eyeZ完全无效。仍然就像我没有“放大/缩小”一样。

我已经像这样设置了ProjectionModelview矩阵和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

我也避免使用正投影法。

0 个答案:

没有答案