java - LibGDX - Bullet - 3D 碰撞检测未检测到碰撞

标签 java libgdx bullet

我正在尝试使用 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,所以我最好使用它。

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

最佳答案

您正在混合碰撞标志 ( 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);
    ...
}

In the spawn method we set this value, using the setUserValue method, to the index of the object in the instances array. And we also inform Bullet that we want to receive collision events for this object by adding the CF_CUSTOM_MATERIAL_CALLBACK flag. This flag is required for the onContactAdded method to be called.

没有理由使用1<<11而不是1<<9用于碰撞过滤。您可能还更改了其他内容(例如碰撞标志),并错误地认为碰撞过滤器中的此更改导致其开始工作。

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

关于java - LibGDX - Bullet - 3D 碰撞检测未检测到碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50224208/

相关文章:

java - JPA映射注释错误org.hibernate.MappingException : Foreign key must have same number of columns as the referenced primary key

用于开发 Android 游戏的 LibGDX 与 Cocos2dx

Java integer++i 不改变值

java - 在 Java 中转发 HTTP 请求

java - System.in available() 调用给出 "Illegal seek"

ios - 在 itunes connect libgdx 上加载应用程序时缺少 iPad/iPhone 图标

java - LibGdx 无法在 iOs 模拟器上启动应用程序

c++ - 2个物体之间的子弹碰撞回调

c++ - 从 btScalar 矩阵获取方向 vector