打开GL投影矩阵与正交射线拾取

时间:2015-09-24 17:14:53

标签: c# vb.net opengl math opentk

背景

我目前正在尝试根据我的鼠标位置进行光线投射,然后将其用于确定它与我的对象相交的位置。到目前为止,我所拥有的是一条连接相机中心和原点的线,这将始终是我的焦点。我能够取消我的鼠标以获得它的x,y,z坐标。我也能够从那个未投影的位置创建一条线,该线与我用相机和原点创建的线平行。

问题

我遇到的问题是新行无法正确投射到我的对象中。我相信这是因为我在投影模式下查看所有内容,从而使一切看起来都是收敛的。我的问题是,如果有办法调整我的线投影以考虑正在发生的收敛?

enter image description here

在上图中,橙色线代表我的新光线,绿色圆圈代表光标所在的位置。通过数学证实,它确实与我的相机与原点矢量平行,但显然不会出现这种情况。我相信这是我正在谈论的融合,但如果你不相信这是真正的问题,请纠正我。

据说我的屏幕上应该出现一个点,因为我点击的投影线将以相同的角度进入屏幕。如果我的所有假设都是真的,那么我该如何解释这种差异呢?

证明我的线条是平行的

为了证明我的线条是平行的,我保存了我的原始矢量和我的新矢量,绘制它们,然后旋转以查看它们的位置。黄线代表从我的相机到原点的线,橙色是新线。我查了一下,黄线的长度等于橙色的长度。此外绿色和紫色相等,这证明我的线是平行的

enter image description here

我的抽奖活动

Private Sub GlControl1_Paint(ByVal sender As System.Object,ByVal e As System.Windows.Forms.PaintEventArgs)处理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 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)

    Dim XL0, YL0, ZL0 As Single
    XL0 = camx
    YL0 = camy
    ZL0 = camz

    'origin is at 0,0,0
    '

    Dim XL1, YL1, ZL1 As Single
    XL1 = 0
    YL1 = 0
    ZL1 = 0

    Dim XS, YS, ZS As Single

    XS = XL1 - XL0
    YS = YL1 - YL0
    ZS = ZL1 - ZL0

    Dim length As Single = Sqrt(XS * XS + YS * YS + ZS * ZS)

    XS /= length
    YS /= length
    ZS /= length


    Dim origin As New Vector3(0, 0, 0)
    Dim mouse_position As New Vector3(returnvec.X, returnvec.Y, returnvec.Z)
    Dim camera_position As New Vector3(cam.Position.X, cam.Position.Y, cam.Position.Z)

    Dim newpoint As Vector3

    newpoint = mouse_position + (origin - camera_position).Normalized * length

    Dim newxs, newys, newzs As Single
    newxs = newpoint.X - returnvec.X
    newys = newpoint.Y - returnvec.Y
    newzs = newpoint.Z - returnvec.Z


    Dim newlength As Single = Sqrt(newxs * newxs + newys * newys + newzs * newzs)

    newxs /= newlength
    newys /= newlength
    newzs /= newlength

    GL.Vertex3(newpoint.X, newpoint.Y, newpoint.Z)
    GL.Vertex3(mouse_position.X, mouse_position.Y, mouse_position.Z)
    GL.End()

    GL.LineWidth(2.0F)
    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.Yellow)
    GL.Vertex3(0, 0, 0)
    GL.Vertex3(camloc(0), camloc(1), camloc(2))
    GL.End()


    GL.Begin(PrimitiveType.Lines)
    GL.Color3(Color.LimeGreen)
    GL.Vertex3(mouse_position.X, mouse_position.Y, mouse_position.Z)
    GL.Vertex3(camloc(0), camloc(1), camloc(2))
    GL.End()

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

    Label4.Text = "green length = " & Sqrt((camloc(0) - mouse_position.X) ^ 2 + (camloc(1) - mouse_position.Y) ^ 2 + (camloc(2) - mouse_position.Z) ^ 2) & _
        " purple length = " & Sqrt((newpoint.X) ^ 2 + (newpoint.Y) ^ 2 + (newpoint.Z) ^ 2)

    Label3.Text = "yellow length = " & Sqrt((camloc(0)) ^ 2 + (camloc(1)) ^ 2 + (camloc(2)) ^ 2) & _
        " orange length = " & Sqrt((newpoint.X - mouse_position.X) ^ 2 + (newpoint.Y - mouse_position.Y) ^ 2 + (newpoint.Z - mouse_position.Z) ^ 2)


    GL.Enable(EnableCap.Lighting)



    draw_extras()


    GL.Flush()
    GlControl1.SwapBuffers()

    Label1.Text = distance
End Sub

我的非项目功能

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

    vec.X = 2.0F * mouse.X / CSng(viewport.Width) - 1
    vec.Y = -(2.0F * mouse.Y / CSng(viewport.Height) - 1)
    vec.Z = 0
    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

SetupViewport功能

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

1 个答案:

答案 0 :(得分:0)

在您的取消投影功能更改

vec.X = 2.0F * mouse.X / CSng(viewport.Width) - 1
vec.Y = -(2.0F * mouse.Y / CSng(viewport.Height) - 1)

 vec.X = 2.0F * mouse.X / CSng(viewport.Width) - 1
vec.Y = 2.0F * mouse.Y / CSng(viewport.Height) - 1