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
提供了一个投影矩阵。谢谢,这确实有意义,并将帮助我更好地理解这些内容