如何从鼠标点击坐标获取WebGL三维空间中的对象
我正在WebGL中构build一个桌面游戏。 该板可以旋转/缩放。 我需要一种方法来将canvas元素(x,y)的点击转换为三维空间(x,y,z)中的相关点。 最终的结果是我想知道包含触及最靠近用户的物体的点的(x,y,z)坐标。 例如,用户点击一个片段,并且想象一下通过3D片段的射线穿过棋子和棋盘,但是我想要棋子的(x,y,z)坐标,感动。
我觉得这是一个非常普遍的问题,但我似乎无法在Google上find解决scheme。 必须有一些方法将3D空间的当前视图投影到2D中,以便可以将2D空间中的每个点映射到3D空间中的相关点。 我希望用户能够将鼠标hover在电路板上的一个空间上,并且具有点改变的颜色。
您正在寻找一个无投影function,将屏幕坐标转换为从相机位置投射到3D世界的光线。 然后,您必须执行光线/三angular形交叉testing,以find与相机相交的最接近的三angular形。
我有一个在jax / camera.js#L568可用的unprojecting的例子 – 但是你仍然需要实现光线/三angular形的交集。 我有一个在jax / triangle.js#L113的实现 。
有一个更简单的(通常)更快的select,但是,被称为“挑选”。 如果要select整个对象(例如棋子),并且不关心鼠标实际点击的位置,请使用此选项。 WebGL的方法是将整个场景渲染成纹理,然后从纹理中渲染出各种不同的蓝色(蓝色是关键,而红色和绿色用于场景中的对象的唯一ID)那个纹理。 将RGB解码成对象的ID会给你点击的对象。 再次,我已经实现了这一点,它可在jax / world.js#L82 。 (另见第146,162,175行)
这两种方法都有优点和缺点(在这里以及在一些评论之后进行讨论),你需要找出哪种方法最适合你的需求。 挑选较慢的场景很大,但在纯JS中的不投影是非常慢的(因为JS本身并不是那么快),所以我最好的build议是试验两者。
仅供参考,您还可以查看GLU项目和非项目代码,这些代码是基于我的代码松散的: http : //www.opengl.org/wiki/GluProject_and_gluUnProject_code
这是工作演示
function onMouseUp(event) { event.preventDefault(); x_pos = (event.clientX / window.innerWidth) * 2 - 1; y_pos = -(event.clientY / window.innerHeight) * 2 + 1; z_pos = 0.5; var vector = new THREE.Vector3( x_pos , y_pos , z_pos ); var projector = new THREE.Projector(); projector.unprojectVector(vector, camera); var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); var intersects = raycaster.intersectObjects(intersectObjects); if (intersects.length > 0) { xp = intersects[0].point.x.toFixed(2); yp = intersects[0].point.y.toFixed(2); zp = intersects[0].point.z.toFixed(2); destination = new THREE.Vector3( xp , yp , zp ); radians = Math.atan2( ( driller.position.x - xp) , (driller.position.z - zp)); radians += 90 * (Math.PI / 180); console.log(radians); var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start(); }
weissner-doors.de/drone/
目前我正在处理这个问题 – 我采取的方法是
- 渲染对象来select具有唯一颜色的缓冲区
- 读取缓冲区像素,映射回拾取的对象
- 渲染拾取的对象以缓冲每个像素颜色的Z深度函数
- 读取缓冲区像素,映射回Z轴深度
- 我们挑选了对象和近似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}; }