如何在WebGL中检测碰撞?

7
如何在WebGL中检测碰撞,而不使用像three.js这样的库?

1
这可能很难做。不管怎样,为什么你不想要一个库来完成它呢? - Derek 朕會功夫
1
@ajax333221 库使我们的生活变得更加轻松。 :) - Derek 朕會功夫
2
@Derek 当我们初学编程时,它们让我们依赖库。 - ajax333221
4个回答

13

如何在WebGL中检测碰撞

不可以。WebGL和OpenGL只用于绘制图形,它们不管理场景,也没有“物体”或诸如碰撞这样的高级概念。它们只处理点、线、三角形和着色器。

与场景管理或碰撞相关的任何内容都超出了WebGL(和OpenGL)的范围。


那么我该如何在JS中计算它呢? - Danny Fox
3
@DannyFox:和其他语言一样,你可以通过解决各种几何交点测试方程并从结果中提取碰撞来计算它。关于这个主题有一本很好的书:http://realtimecollisiondetection.net/。 - datenwolf
1
你可以通过使用着色器在OpenGL(和可能的WebGL)中解决碰撞问题。给物体不同的颜色,然后使用混合将两个对象组合起来。如果结果图像上有一个或多个像素与两个对象的颜色不同(例如,某些像素从一个对象与其他对象的像素混合),则存在碰撞。 - Willem
@Willem:那种方法在3D中不起作用。如果有两个不相交的球体,其中一个仅遮挡另一个呢?而且在2D中,这也是一种相当慢的方法,因为你必须将所有像素的颜色与所有对象的颜色进行比较。这个复杂度是O(n×m),通常写成O(n²)。使用适当的碰撞检测方法,可以在空间细分结构上操作,通常可以实现O(n log(n)),但通常实际上接近于O(n)。 - datenwolf
1
它肯定是为2D使用而设计的(虽然3D可能也可以,但我没有考虑过)。与其他解决方案(如光线追踪、几何模型等)相比,性能取决于上下文。您可以将实体对象渲染为灰色,并在黑色背景的单个图像上进行叠加混合。然后在生成的图像中运行快速检查,以查看是否存在一个或多个白色像素。如果有,请检查它们的位置并运行计算。在像JS这样的平台上,物理学很慢,WebGL着色器的硬件加速可以提高性能。 - Willem

3
一种简单的方法是在GPU上进行光线碰撞检测。请查看以下与该主题相关的博客文章。 http://blog.xeolabs.com/ray-picking-in-scenejs 主要思路是使用一个保存对象ID而不是颜色的着色器将场景渲染到纹理(使用FBO)。然后,您可以快速查找此纹理以查看光线与哪些物体相交。

这仅适用于测试从视点出发的射线或具有非遮挡几何图形。 - datenwolf
是的,这个解决方案只适用于光线碰撞,但问题没有说明需要什么类型的碰撞检测。我的观点是,在GPU上可以完美地运行一些碰撞测试(但这不是通用解决方案)。 - Mortennobel
谢谢,但它是在scene.js中。我想不使用任何库来完成它。 - Danny Fox
是的 - 但是将其移植到任何WebGL应用程序中相当容易(我自己将其移植到了KickJS)。 - Mortennobel

1

我会推荐以下网页(很遗憾只提供德文)http://www.peter-strohm.de/webgl/webgltutorial8.php

我们能够实现碰撞检测并且甚至可以使用ID映射在服务器上执行API调用(例如,在场景中为某个特定对象显示工具提示的附加信息)。

希望这有些帮助。


1

从周日开始,我一直在尝试解决同样的问题。虽然在互联网上有很多信息,但我无法让它在我的示例程序中正常工作。一旦我解决了它,我会在这里发布我的示例。

我最后的尝试是使用glu-unProject端口用于webGL。这需要以下参数:

function(winX, winY, winZ, model, proj, view, objPos)

为了测试目的,我尝试直接从我的场景绘制函数调用此函数。

var pMatrix  = new mat4.ortho(iL, iR, iB, iT, fNearZ, farZ);
var mvMatrix = new mat4.create();

mat4.identity(mvMatrix);
mat4.translate(mvMatrix,[0,0,-40]);

var oMouseMatrix = mat4.create();
mat4.identity(oMouseMatrix);

//Rotate eye :-S
mat4.rotate(oMouseMatrix,((this.fAnimationXAngle/10) * Math.PI) / 360.0,[0,1,0]);
mat4.rotate(oMouseMatrix,((this.fAnimationYAngle/10) * Math.PI) / 360.0,[1,0,0]);

mat4.multiply(oMouseMatrix, mvMatrix, mvMatrix);

//Rotate model
mat4.rotateX(mvMatrix,this.fRotX * Math.PI / 180.0);
mat4.rotateY(mvMatrix,this.fRotY * Math.PI / 180.0);
mat4.rotateZ(mvMatrix,this.fRotZ * Math.PI / 180.0);



var aTest = this.unProject(
    this.pLastMouse.x,
    this.pLastMouse.y,
    0,
    mvMatrix,
    pMatrix,
    [0,0,this.iWidth,this.iHeight]
);

this.iWidth和this.iHeight是画布和视口的宽度/高度 - this.pLastMouse.x和.y是画布内鼠标坐标

zI.debug(aTest);

但结果非常糟糕。我猜我的代码里有几个错误。我上周五才开始尝试WebGL。我不想这么早就放弃,但自那以后我已经解决了很多问题,但这个问题让我发疯。

在OpenGL中对我来说要容易得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接