elm webgl中光线投射的对象拾取

elm webgl中光线投射的对象拾取,webgl,elm,Webgl,Elm,演示几乎(?)工作示例: 演示:单击以绘制光线,并左右旋转摄影机以查看光线。(由于原点来自摄影机,因此从创建原点的位置看不到原点) 上下文 我正在做一个elm&elmwebgl项目,我想知道鼠标单击时是否在对象上。要做的是我尝试实现一个简单的光线投射。我需要的是两件事: 1) 摄像机的坐标(这个很容易) 2) 单击位置的三维空间中的坐标/方向 问题 据我所知,从二维视图空间到三维世界空间的步骤如下: a) 使坐标相对于视图端口在-1到1的范围内 b) 反转投影矩阵和透视矩阵 c) 乘法投影和透视

演示几乎(?)工作示例:
演示:单击以绘制光线,并左右旋转摄影机以查看光线。(由于原点来自摄影机,因此从创建原点的位置看不到原点)

上下文
我正在做一个elm&elmwebgl项目,我想知道鼠标单击时是否在对象上。要做的是我尝试实现一个简单的光线投射。我需要的是两件事:
1) 摄像机的坐标(这个很容易)
2) 单击位置的三维空间中的坐标/方向

问题
据我所知,从二维视图空间到三维世界空间的步骤如下:
a) 使坐标相对于视图端口在-1到1的范围内
b) 反转投影矩阵和透视矩阵
c) 乘法投影和透视矩阵
d) 从标准化鼠标坐标创建矢量4
e) 将组合矩阵与向量4相乘
f) 标准化结果

尝试到目前为止
我制作了一个函数来转换鼠标。将鼠标定位到坐标以绘制直线:

getClickPosition : Model -> Mouse.Position -> Vec3
getClickPosition model pos =
    let
        x =
            toFloat pos.x

        y =
            toFloat pos.y

        normalizedPosition =
            ( (x * 2) / 1000 - 1, (1 - y / 1000 * 2) )

        homogeneousClipCoordinates =
            Vec4.vec4
                (Tuple.first normalizedPosition)
                (Tuple.second normalizedPosition)
                -1
                1

        inversedProjectionMatrix =
            Maybe.withDefault Mat4.identity (Mat4.inverse (camera model))

        inversedPerspectiveMatrix =
            Maybe.withDefault Mat4.identity (Mat4.inverse perspective)

        inversedMatrix2 =
            Mat4.mul inversedProjectionMatrix inversedPerspectiveMatrix

        to =
            Vec4.vec4
                (Tuple.first normalizedPosition)
                (Tuple.second normalizedPosition)
                1
                1

        toInversed =
            mulVector inversedMatrix2 to

        toNorm =
            Vec4.normalize toInversed

        toVec3 =
            vec3 (Vec4.getX toNorm) (Vec4.getY toNorm) (Vec4.getZ toNorm)
    in
        toVec3
结果
此函数的结果是光线太过偏离我单击的中心。我添加了一个屏幕截图,点击了立方体顶部的四个面。如果单击视口的中心,光线将正确定位

感觉很接近,但还没有完全达到,我不知道我做错了什么


尝试其他方法后,我找到了一个解决方案:

getClickPosition : Model -> Mouse.Position -> Vec3
getClickPosition model pos =
    let
        x =
            toFloat pos.x

        y =
            toFloat pos.y

        normalizedPosition =
            ( (x * 2) / 1000 - 1, (1 - y / 1000 * 2) )

        homogeneousClipCoordinates =
            Vec4.vec4
                (Tuple.first normalizedPosition)
                (Tuple.second normalizedPosition)
                -1
                1

        inversedViewMatrix =
            Maybe.withDefault Mat4.identity (Mat4.inverse (camera model))

        inversedProjectionMatrix =
            Maybe.withDefault Mat4.identity (Mat4.inverse perspective)

        vec4CameraCoordinates = mulVector inversedProjectionMatrix homogeneousClipCoordinates

        direction = Vec4.vec4 (Vec4.getX vec4CameraCoordinates) (Vec4.getY vec4CameraCoordinates) -1 0

        vec4WorldCoordinates = mulVector inversedViewMatrix direction

        vec3WorldCoordinates = vec3 (Vec4.getX vec4WorldCoordinates) (Vec4.getY vec4WorldCoordinates) (Vec4.getZ vec4WorldCoordinates)

        normalizedVec3WorldCoordinates = Vec3.normalize vec3WorldCoordinates

        origin = model.cameraPos

        scaledDirection = Vec3.scale  20 normalizedVec3WorldCoordinates

        destination = Vec3.add origin scaledDirection

    in
        destination
我留下了尽可能详细的,如果有人发现我使用了不正确的术语,请作出评论,我会更新答案

我相信有很多优化方法是可能的(在反转或组合某些步骤之前乘以矩阵)


更新了ellie应用程序:

我认为Mat4.makeLookAt中的函数返回投影和视图矩阵的乘法。我在elm webgl
Mat4中的任何地方都找不到投影矩阵的其他参考。makeLookAt
提供了一个视图矩阵,而
Mat4。makePerspective
提供了一个投影矩阵。谢谢,这确实有意义,并将帮助我更好地理解这些内容