我正在用WebGL构建一个棋盘游戏。可以旋转/缩放棋盘。我需要一种方法来将单击画布元素(x,y)转换为3D空间中的相关点(x,y,z)。最终的结果是我想知道(x,y,z)坐标,它包含与用户最接近的对象的接触点。例如,用户单击一个棋子,您想象一条光线穿过3D空间,穿过棋子和游戏板,但我想要的是棋子在触摸点上的(x,y,z)坐标。
我觉得这肯定是一个很常见的问题,但我似乎在我的谷歌中找不到解决方案。必须有某种方法将三维空间的当前视图投影到二维,以便可以将二维空间中的每个点映射到三维空间中的相关点。我希望用户能够将鼠标放在板上的一个空间上,并有点改变颜色。
发布于 2011-09-10 18:27:51
您正在寻找一个非投影函数,该函数将屏幕坐标转换为从相机位置到3D世界的光线投射。然后,必须执行光线/三角形相交测试,以查找与摄影机最近的三角形,该三角形也与光线相交。
我在jax/camera.js#L568上提供了一个取消投影的示例--但是您仍然需要实现光线/三角形相交。我在jax/triangle.js#L113上实现了这一点。
然而,还有一种更简单、(通常)更快的选择,叫做“挑选”。如果要选择整个对象(例如,国际象棋棋子),并且不关心鼠标实际单击的位置,请使用此选项。执行此操作的WebGL方法是将整个场景以各种不同的蓝色(蓝色是关键点,而红色和绿色用于场景中对象的唯一ID)渲染到一个纹理,然后从该纹理读回一个像素。将RGB解码为对象的ID将得到所单击的对象。同样,我已经实现了这一点,可以在jax/world.js#L82上找到它。(另参见第146、162、175行。)
这两种方法各有优缺点(在后面的一些评论中讨论了here ),您需要找出哪种方法最适合您的需求。对于大型场景,拾取速度较慢,但在纯JS中取消投影非常慢(因为JS本身并不是那么快),所以我最好的建议是同时尝试这两种方式。
仅供参考,您还可以查看GLU项目和非项目代码,我的代码大致基于这些代码:http://www.opengl.org/wiki/GluProject_and_gluUnProject_code
发布于 2011-10-16 13:44:54
我现在正在解决这个问题--我采取的方法是
发布于 2013-06-28 08:44:33
这是工作演示
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/
https://stackoverflow.com/questions/7364693
复制