如何在WebGL 3d空间中从鼠标点击坐标获取对象

How to get object in WebGL 3d space from a mouse click coordinate

本文关键字:鼠标 坐标 取对象 获取 WebGL 3d 空间      更新时间:2023-09-26

我正在WebGL中创建一个桌面游戏。这块板可以旋转/缩放。我需要一种方法将画布元素(x,y)上的点击转换为3D空间中的相关点(x,y, z),最终结果是我想知道(x,y, z)坐标,该坐标包含与用户最接近的对象接触的点。例如,用户点击一个部件,你想象一条射线穿过3D空间,穿过部件和游戏板,但我想要的是部件的(x, y, z)坐标在它被触摸的点。

我觉得这一定是一个非常普遍的问题,但我似乎在我的谷歌中找不到解决方案。必须有某种方法将3D空间的当前视图投射到2D中,这样您就可以将2D空间中的每个点映射到3D空间中的相关点。我希望用户能够将鼠标移到黑板上的一个空间上,并让该点改变颜色。

您正在寻找一个非投影函数,它将屏幕坐标转换为从摄像机位置到3D世界的光线投射。然后,必须执行光线/三角形相交测试,以找到距离相机最近且与光线相交的三角形。

我在jax/camera.js#L568中有一个取消投影的例子,但你仍然需要实现光线/三角形相交。我在jax/triangle.js#L113中有一个实现。

然而,有一个更简单(通常)更快的选择,叫做"挑选"。如果您想要选择整个对象(例如,一个棋子),或者您不关心鼠标实际点击的位置,则使用此选项。WebGL做到这一点的方法是将整个场景用不同深浅的蓝色(蓝色是一个键,而红色和绿色用于场景中对象的唯一id)渲染到一个纹理,然后从该纹理中读取一个像素。将RGB解码为对象的ID将为您提供被单击的对象。同样,我已经实现了这个,它在jax/world.js#L82中可用。(另见第146、162、175行)

两种方法都有优点和缺点(在这里和后面的一些评论中讨论),您需要找出哪种方法最适合您的需求。在巨大的场景中选择会更慢,但在纯JS中取消投影非常慢(因为JS本身并不是那么快),所以我最好的建议是同时尝试两种方法。

仅供参考,您还可以查看GLU项目和非项目代码,我的代码松散地基于:http://www.opengl.org/wiki/GluProject_and_gluUnProject_code

我现在正在研究这个问题-我采取的方法是

  1. 渲染对象选择缓冲区,每个对象具有独特的颜色
  2. 读取缓冲区像素,映射回选中的对象
  3. 用Z-depth函数的每个像素颜色渲染选定的对象到缓冲区
  4. 读取缓冲区像素,映射回Z-depth
  5. 我们已经拾取了对象和拾取坐标的近似Z

从其中一个线程中。不确定(x,y,z)但是你可以用

得到canvas(x,y)

getBoundingClientRect ()

function getCanvasCoord(){
  var mx = event.clientX;
  var my = event.clientY;
  var canvas = document.getElementById('canvasId');
  var rect = canvas.getBoundingClientRect();// check if your browser supports this
  mx = mx - rect.left;
  my = my - rect.top;
  return {x: mx , y: my};
}