将屏幕坐标转换为世界坐标,不用GLUUNPROJECT

时间:2015-09-18 20:59:31

标签: vb.net opengl math matrix opentk

我一直在搜索谷歌和本网站的答案,但我仍然对如何将屏幕上的坐标转换为模型空间中的坐标感到困惑。我知道从原点(0,0,0)到我的相机的距离,这也是视口的中心:

enter image description here

如果我在视图窗口中有不同的点,例如(1,3):

enter image description here

在数学视图中以数学方式计算新点或使用矩阵函数来确定它的最佳方法是什么?

如果对某些人来说这被认为是“容易”,我很抱歉,但我希望有人会使用我的样本坐标发布一个很好的例子,因为我仍然很困惑。

这是在每一帧上完成的矩阵调用:

Public Sub SetupViewport()
    Dim w As Integer = GlControl1.Width
    Dim h As Integer = GlControl1.Height
    Dim perspective1 As Matrix4 = cam.GetViewMatrix() * Matrix4.CreatePerspectiveFieldOfView(1.3F, ClientSize.Width / CSng(ClientSize.Height), 0.1F, 200.0F)


    GL.MatrixMode(MatrixMode.Projection)
    GL.LoadIdentity()
    GL.LoadMatrix(perspective1)
    GL.Viewport(0, 0, w, h)

End Sub

这样做是为了让我使用凸轮矩阵旋转相机。我通常在Open GL中知道您旋转场景而不是相机,但因为我将其用作CAD程序,所以我将相机旋转到原点。

出于测试目的,我一直在构建一条从我计算的计算起点到原点的线。正如标题所述,我不想使用gluunproject,因为我已经读过这是基于Tao框架所以不应该使用。

我的抽奖子

Private Sub GlControl1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint

    GL.Clear(ClearBufferMask.ColorBufferBit)
    GL.Clear(ClearBufferMask.DepthBufferBit)
    GL.DepthMask(True)
    GL.Enable(EnableCap.DepthTest)
    GL.ClearDepth(1.0F)



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


    Dim lightColor0 As Single() = {intensity, intensity, intensity, 1.0F}
    Dim lightPos0 As Single() = {camx, camy, camz, 1.0F}


    GL.Light(LightName.Light0, LightParameter.Diffuse, lightColor0)
    GL.Light(LightName.Light0, LightParameter.Position, lightPos0)
    GL.Enable(EnableCap.Light0)



    Dim mat_specular As Single() = {1.0F, 1.0F, 1.0F, 1.0F}
    Dim mat_shininess As Single() = {50.0F}


    GL.Material(MaterialFace.Front, MaterialParameter.Specular, mat_specular)
    GL.Material(MaterialFace.Front, MaterialParameter.Shininess, mat_shininess)


    GL.Disable(EnableCap.Lighting)

    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.Red)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(100, 0, 0)

    GL.Color3(Color.Green)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(0, 100, 0)

    GL.Color3(Color.Blue)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(0, 0, 100)
    GL.End()


    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.DarkRed)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(-100, 0, 0)

    GL.Color3(Color.DarkGreen)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(0, -100, 0)

    GL.Color3(Color.DarkBlue)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(0, 0, -100)
    GL.End()

    Dim projmatrix As Matrix4
    GL.GetFloat(GetPName.ProjectionMatrix, projmatrix)
    Dim mouse_ As New Vector2(_mouseStartX, _mouseStartY)
    Dim returnvec As Vector4

    returnvec = UnProject(projmatrix, cam.GetViewMatrix(), GlControl1.Size, mouse_)

    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.Orange)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(returnvec.X, returnvec.Y, returnvec.Z)
    GL.End()


    GL.Enable(EnableCap.Lighting)

    draw_extras()


    GL.Flush()
    GlControl1.SwapBuffers()
End Sub

1 个答案:

答案 0 :(得分:1)

感谢datenwolf让我走上了正确的道路。我为解决我的问题所做的是在一些网站的帮助下编写了一个unproject函数:

Dim projmatrix As Matrix4
    GL.GetFloat(GetPName.ProjectionMatrix, projmatrix)
    Dim modelmatrix As Matrix4
    GL.GetFloat(GetPName.ModelviewMatrix, modelmatrix)

    Dim mouse_ As New Vector2(_mouseStartX, _mouseStartY)
    Dim returnvec As Vector4

    returnvec = UnProject(projmatrix, modelmatrix, GlControl1.Size, mouse_)

    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.Orange)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(returnvec.X, returnvec.Y, returnvec.Z)
    GL.End()

我有一个鼠标移动事件处理程序,它只是捕获屏幕上的鼠标位置并将坐标保存到两个全局变量。在我的绘制函数中,我然后调用我的新函数并绘制一条从原点延伸到我的行鼠标位置:

Public Sub SetupViewport()
    Dim w As Integer = GlControl1.Width
    Dim h As Integer = GlControl1.Height

    Dim perspective1 As Matrix4 = cam.GetViewMatrix() * Matrix4.CreatePerspectiveFieldOfView(1.3F, ClientSize.Width / CSng(ClientSize.Height), 0.1F, 200.0F)


    GL.MatrixMode(MatrixMode.Projection)
    GL.LoadIdentity()
    GL.LoadMatrix(perspective1)
    GL.MatrixMode(MatrixMode.Modelview)
    GL.LoadIdentity()
    GL.Viewport(0, 0, w, h)
    GL.Enable(EnableCap.DepthTest)
    GL.DepthFunc(DepthFunction.Less)

End Sub

我还必须更改setupviewport功能:

String

结果是一条线的一侧始终位于原点,而另一侧始终位于鼠标所在的位置,这是显示此工作的绝佳示例。

enter image description here