如何获得对象WebGL的3D空间,从鼠标点击的坐标坐标、如何获得、鼠标点击、对象

2023-09-07 17:09:50 作者:十里故清欢

我要建在WebGL的一个棋盘游戏。该板可以旋转/缩放。我需要一个方法来翻译所述画布元件(X,Y)上的点击进入在三维空间(X,Y,Z)中的相关点。最终的结果是,我想知道的(X,Y,Z)坐标,包含触摸最接近用户的对象的点。例如,用户点击了一块,和你想象的光线通过三维空间中经过两个片和游戏板旅行,但我想要的一块(X,Y,Z)坐标处的地步,这是感动。

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.

我觉得这一定是一个非常普遍的问题,但我似乎无法找到我的谷歌的解决方案。必须有某种方式来推算三维空间的当前视图到2D这样你就可以在二维空间中的每个点映射到三维空间中的相关点。我想用户能够鼠标在板上的空间,并有斑点变色

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.

推荐答案

您正在寻找一个unproject功能,把屏幕坐标转换到从相机位置的光线投射到3D世界。然后,您必须执行射线/三角形相交测试,以找到最接近的三角相机也相交线。

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.

我有unprojecting可在jax/camera.js#L568 - 但你仍然需要实现光线/三角形交点。我有一个实现在jax/triangle.js#L113.

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.

还有一个更简单的和(通常情况下)更快的替代方案,但是,所谓的采摘。如果你想选择一个完整的对象(例如,一个棋子)使用这个,如果你不关心那里的鼠标实际点击。 WebGL的方式做到这一点是使蓝色的各种色调(蓝色是一个键,而红色和绿色被用于在场景中的对象的唯一ID),以将纹理整个场景,然后回读从像素纹理。解码的RGB到对象的ID会给你被点击的对象。再次,我已经实现了这一点,它可以在jax/world.js#L82. (参见线146,162,175。)

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.)

这两种方法各有利弊(讨论这里和一些评论后),你需要找出哪种方法最适合您的需要。采摘较慢巨大的场面,但unprojecting纯JS是非常慢(因为JS本身是不是所有的快),所以我最好的建议是尝试两者。

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.

仅供参考,你也可以看看GLU项目和unproject code,这是我根据我的code宽松时:http://www.opengl.org/wiki/GluProject_and_gluUnProject_$c$c

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