首页 文章

如何检测three.js中的碰撞? [关闭]

提问于
浏览
40

我正在使用three.js .

我的场景中有两个网格几何体 .

如果这些几何形状相交(或者如果被翻译则相交)我想将其检测为碰撞 .

如何使用three.js执行碰撞检测?如果three.js没有碰撞检测设施,是否还有其他库可以与three.js结合使用?

2 回答

  • 94

    在SO问题中,这个问题确实太过广泛,但为了润滑网站的搜索引擎优化,这里有几个简单的起点:

    如果你想要真正简单的碰撞检测而不是一个完整的物理引擎,那么请查看Three.js: Simple Collision Detection

    另一方面,如果你想要一些碰撞响应,而不仅仅是"did A and B bump?",请看一下Physijs,这是一个非常容易使用的围绕Three.js构建的Ammo.js包装器

  • 6

    在Three.js中,似乎不再支持实用程序CollisionUtils.js和Collisions.js,并且mrdoob(three.js的创建者)自己建议更新到最新版本的three.js并使用Ray类来实现此目的代替 . 以下是一种解决方法 .

    这个想法是这样的:假设我们要检查一个名为“Player”的给定网格是否与名为“collidableMeshList”的数组中包含的任何网格相交 . 我们可以做的是创建一组光线,这些光线从Player网格(Player.position)的坐标开始,并向Player网格几何体中的每个顶点延伸 . 每个Ray都有一个名为“intersectObjects”的方法,它返回Ray与之相交的对象数组,以及每个对象的距离(从Ray的原点开始测量) . 如果到交叉点的距离小于玩家位置和几何体顶点之间的距离,则碰撞发生在玩家网格的内部 - 我们可能称之为“实际”碰撞 .

    我发布了一个工作示例:

    http://stemkoski.github.io/Three.js/Collision-Detection.html

    您可以使用箭头键移动红色线框立方体,并使用W / A / S / D旋转它 . 当它与其中一个蓝色立方体相交时,如上所述,对于每个交叉点,单词“Hit”将出现在屏幕顶部一次 . 代码的重要部分如下 .

    for (var vertexIndex = 0; vertexIndex < Player.geometry.vertices.length; vertexIndex++)
    {       
        var localVertex = Player.geometry.vertices[vertexIndex].clone();
        var globalVertex = Player.matrix.multiplyVector3(localVertex);
        var directionVector = globalVertex.subSelf( Player.position );
    
        var ray = new THREE.Ray( Player.position, directionVector.clone().normalize() );
        var collisionResults = ray.intersectObjects( collidableMeshList );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) 
        {
            // a collision occurred... do something...
        }
    }
    

    这种特殊方法存在两个潜在的问题 .

    (1)当光线的原点在网格M内时,将不返回光线和M之间的碰撞结果 .

    (2)小的(相对于玩家网格)的物体可能在各种射线之间“滑动”,因此不会记录碰撞 . 减少此问题几率的两种可能方法是编写代码,以便小对象创建光线并从其视角执行碰撞检测工作,或在网格上包含更多顶点(例如,使用CubeGeometry(100,100,100, 20,20,20)而不是CubeGeometry(100,100,100,1,1,1) . )后一种方法可能会导致性能下降,所以我建议谨慎使用它 .

    我希望其他人能够通过解决这个问题的方式为这个问题做出贡献 . 在开发这里描述的解决方案之前,我在这方面已经挣扎了很长一段时间 .

相关问题