如何从鼠标单击坐标获取 WebGL 3d 空间中的对象
我正在 WebGL 中构建一个棋盘游戏。该板可以旋转/缩放。我需要一种方法将画布元素 (x,y) 上的点击转换为 3D 空间中的相关点 (x, y, z)。最终的结果是我想知道包含接触最接近用户的对象的点的(x,y,z)坐标。例如,用户单击一块,您想象一条光线穿过 3D 空间,穿过该块和游戏板,但我想要该块在其所在位置的 (x, y, z) 坐标感动。
我觉得这一定是一个很常见的问题,但我似乎无法在我的谷歌中找到解决方案。必须有某种方法将 3D 空间的当前视图投影到 2D,以便您可以将 2D 空间中的每个点映射到 3D 空间中的相关点。我希望用户能够将鼠标悬停在板上的空间上,并让该点改变颜色。
I'm building a boardgame in WebGL. The board can be rotated/zoomed. I need a way to translate a click on the canvas element (x,y) into the relevant point in 3D space (x, y, z). The ultimate result is that I want to know the (x, y, z) coordinate that contains the point that touches the object closest to the user. For instance, the user clicks a piece, and you imagine a ray traveling through 3D space that goes through both the piece and the game board, but I want the (x, y, z) coord of the piece at the point where it was touched.
I feel like this must be a very common problem, but I can't seem to find a solution in my googles. There must be some way to project the current view of the 3D space into 2D so you can map each point in 2D space to the relevant point in 3D space. I want to the user to be able to mouse over a space on the board, and have the spot change color.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正在寻找一个 unproject 函数,它将屏幕坐标转换为从相机位置投射到 3D 世界的光线。然后,您必须执行光线/三角形相交测试,以找到距离相机最近且与光线相交的三角形。
我有一个取消投影的示例,位于 jax/camera.js#L568< /a> -- 但你仍然需要实现射线/三角形相交。我在 jax/triangle.js#L113。
然而,有一个更简单且(通常)更快的替代方案,称为“挑选”。如果您想要选择整个对象(例如,棋子)并且不关心鼠标实际单击的位置,请使用此选项。 WebGL 的方法是将整个场景以各种蓝色色调(蓝色是关键,而红色和绿色用于场景中对象的唯一 ID)渲染到纹理,然后从那个纹理。将 RGB 解码为对象的 ID 将得到被单击的对象。再次,我已经实现了这个,它可以在 jax/world.js 中找到。 #L82。 (另请参见第 146、162、175 行。)
两种方法各有利弊(此处讨论< /a> 以及之后的一些评论),您需要找出哪种方法最能满足您的需求。对于巨大的场景,选取速度较慢,但纯 JS 中的非投影速度非常慢(因为 JS 本身并不是那么快),所以我最好的建议是尝试两者。
仅供参考,您还可以查看 GLU 项目和 unproject 代码,我的代码松散地基于它:http://www.opengl。 org/wiki/GluProject_and_gluUnProject_code
You're looking for an unproject function, which converts screen coordinates into a ray cast from the camera position into the 3D world. You must then perform ray/triangle intersection tests to find the closest triangle to the camera which also intersects the ray.
I have an example of unprojecting available at jax/camera.js#L568 -- but you'll still need to implement ray/triangle intersection. I have an implementation of that at jax/triangle.js#L113.
There is a simpler and (usually) faster alternative, however, called 'picking'. Use this if you want to select an entire object (for instance, a chess piece), and if you don't care about where the mouse actually clicked. The WebGL way to do this is to render the entire scene in various shades of blue (the blue is a key, while red and green are used for unique IDs of the objects in the scene) to a texture, then read back a pixel from that texture. Decoding the RGB into the object's ID will give you the object that was clicked. Again, I've implemented this and it's available at jax/world.js#L82. (See also lines 146, 162, 175.)
Both approaches have pros and cons (discussed here and in some of the comments after) and you'll need to figure out which approach best serves your needs. Picking is slower with huge scenes, but unprojecting in pure JS is extremely slow (since JS itself isn't all that fast) so my best recommendation would be to experiment with both.
FYI, you could also look at the GLU project and unproject code, which I based my code loosely upon: http://www.opengl.org/wiki/GluProject_and_gluUnProject_code
我目前正在解决这个问题 - 我正在采取的方法是
I'm working on this problem at the moment - the approach I'm taking is
从一根线中崇拜出来。
不确定 (x,y,z),但您可以使用
canvas(x,y)
culted from one of the threads.
not sure about (x,y,z) but you can get the
canvas(x,y)
using