【发布时间】:2017-09-11 19:19:30
【问题描述】:
演示几乎(?)工作示例:https://ellie-app.com/4h9F8FNcRPya1/1
演示:点击绘制射线,左右旋转相机查看射线。 (由于原点来自相机,所以从创建的位置看不到)
上下文
我正在研究一个 elm 和 elm-webgl 项目,我想知道单击时鼠标是否在对象上方。要做的是我尝试实现一个简单的光线投射。我需要的是两件事:
1)相机坐标(这个很简单)
2) 点击位置在 3D 空间中的坐标/方向
问题
据我了解,从 2D 视图空间到 3D 世界空间的步骤是:
a) 使坐标相对于视口在 -1 到 1 的范围内
b) 反转投影矩阵和透视矩阵
c) 将投影和透视矩阵相乘
d) 从标准化鼠标坐标创建 Vector4
e) 将组合矩阵与 Vector4 相乘
f) 归一化结果
到目前为止尝试
我制作了一个函数来将 Mouse.Position 转换为坐标以绘制一条线:
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
结果
这个函数的结果是光线太靠近我点击的中心。我添加了一个截图,点击了立方体的所有四个顶面。如果我单击视口的中心,光线将被正确定位。
感觉很接近,但还不完全到那里,我不知道我做错了什么!
【问题讨论】:
-
我认为 Mat4.makeLookAt 中的函数返回投影和视图矩阵的乘积。 package.elm-lang.org/packages/elm-community/linear-algebra/… 我在 elm-webgl 的任何地方都找不到投影矩阵的其他参考
-
Mat4.makeLookAt给出一个视图矩阵,Mat4.makePerspective给出一个投影矩阵。 -
谢谢,这确实有道理,将帮助我更好地理解这些事情