【问题标题】:LibGDX - Bullet - 3D collision detection not detecting collisionsLibGDX - Bullet - 3D 碰撞检测未检测到碰撞
【发布时间】:2018-05-08 00:35:47
【问题描述】:

我正在尝试使用 Bullet 进行 3D 碰撞测试,我希望它可以相当简单地工作:

@Override
public void create(){
   . . .
   /*
    * Collision
    */

   collisionConfig=new btDefaultCollisionConfiguration();
   dispatcher=new btCollisionDispatcher(collisionConfig);
   broadphase=new btDbvtBroadphase();
   world=new btCollisionWorld(dispatcher, broadphase, collisionConfig);
   contactListener=new PiscesContactListener();
   contactListener.enable();

   /*
    * Test stuff
    */

   btSphereShape sphere=new btSphereShape(2.5f);
   btCollisionObject object1=new btCollisionObject();
   btCollisionObject object2=new btCollisionObject();
   object1.setCollisionShape(sphere);
   object2.setCollisionShape(sphere);
   object1.setWorldTransform(new Matrix4(new Vector3(0f, 0f, 0f), new Quaternion(0f, 0f, 0f, 0f), new Vector3(1f, 1f, 1f)));
   object2.setWorldTransform(new Matrix4(new Vector3(1f, 0f, 0f), new Quaternion(0f, 0f, 0f, 0f), new Vector3(1f, 1f, 1f)));
   object1.setUserValue(0);
   object2.setUserValue(1);
   object1.setCollisionFlags(WorldObject.COLLISION_PRIMARY);   // 1<<9
   object2.setCollisionFlags(WorldObject.COLLISION_PRIMARY);
   world.addCollisionObject(object1, WorldObject.COLLISION_PRIMARY, WorldObject.COLLISION_EVERYTHING);   // -1
   world.addCollisionObject(object2, WorldObject.COLLISION_PRIMARY, WorldObject.COLLISION_EVERYTHING);
   . . .
}

@Override
public void render() {
   . . .
   world.performDiscreteCollisionDetection();
   . . .
}

/*
 * In a separate file
 */
public class PiscesContactListener extends ContactListener {   
    public boolean onContactAdded (int userValue0, int partId0, int index0, boolean match0, int userValue1, int partId1, int index1, boolean match1) {
        System.out.println("Collision detected between "+userValue0+" and "+userValue1);
        return true;
    }
}

(我遵循了this 指南,尽管我显然稍微偏离了它,试图让它变得更简单。)

在 (0, 0, 0) 处的 2.5 单位球体和在 (1, 0, 0) 处的 2.5 单位球体应该会引起碰撞,不是吗?控制台窗口中没有显示任何内容。

我有点怀疑我忘记了一些基本的东西,因为我试图做一个raycast,但这也不起作用。

可能值得一提的是,调用world.drawDebugWorld(); 会绘制所有对象的线框,所以现在我怀疑错误在于联系人侦听器或者我正在使用的标志(尽管我没有任何其他碰撞标志的运气)。我在联系人监听器中遗漏了什么吗?

另外,我尝试使用ContactCache 而不是ContactListener,但这也没有用。我能找到的关于这件事的大多数阅读材料都是关于ContactListener,所以我最好还是使用它。

我显然忘记了一些事情,因为其他人能够做到这一点,有人能指出那可能是什么吗?

【问题讨论】:

    标签: java libgdx bullet


    【解决方案1】:

    您正在混合碰撞标志 (btCollisionObject#setCollisionFlags(int *flags*)) 和碰撞过滤 (btCollisionWorld#addCollisionObject(object, short *group*, short *mask*))。这是两种截然不同的东西。

    您应该不使用可用标志以外的任何内容调用btCollisionObject#setCollisionFlags(int) 方法(请参阅here)。 CF_CUSTOM_MATERIAL_CALLBACK 碰撞标志 must be set 用于调用 ContactListener#onContactAdded 方法。这就是为什么您的代码无法按预期工作的原因。

    请注意,在我的教程中,您指的是this is explained:

    public void spawn() {
        ...
        obj.body.setUserValue(instances.size);
        obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
        ...
    }
    

    在 spawn 方法中,我们使用 setUserValue 方法将此值设置为实例数组中对象的索引。我们还通过添加CF_CUSTOM_MATERIAL_CALLBACK 标志通知 Bullet 我们希望接收此对象的碰撞事件。 要调用 onContactAdded 方法需要此标志。

    没有理由使用1&lt;&lt;11 代替1&lt;&lt;9 进行冲突过滤。您可能还更改了其他内容(例如碰撞标志),并错误地认为碰撞过滤器中的这种更改导致它开始工作。

    请注意,除了冲突标志和冲突过滤之外,还有(特定于 libgdx 的)contact callback filtering(在该教程的 second part 中进行了解释)。请记住,这是三件完全不同且不相关的事情。

    【讨论】:

    • 有趣,这可能也解释了我遇到的其他一些问题。感谢您指出这些!
    猜你喜欢
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 2014-05-15
    相关资源
    最近更新 更多