简体   繁体   English

LibGDX-项目符号-3D碰撞检测未检测到碰撞

[英]LibGDX - Bullet - 3D collision detection not detecting collisions

I'm trying to do a 3D collision test with Bullet, which I would have expected to work fairly simply: 我正在尝试使用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;
    }
}

(I followed this guide, though I obviously deviated from it a little to try to make it even simpler.) (我遵循了指南,尽管我显然偏离了它一点,试图使其变得更加简单。)

A 2.5-unit sphere at (0, 0, 0) and a 2.5-unit sphere at (1, 0, 0) should cause a collision, should they not? (0,0,0)处的2.5个单位球体和(1、0,0)处的2.5个单位球体应该引起碰撞,不是吗? Nothing's appearing in the console window. 控制台窗口中没有任何内容。

I somewhat suspect there's something fundamental that I'm forgetting, since I tried to do a raycast and that isn't working either. 我有点怀疑我遗忘了一些基本的东西,因为我尝试进行光线投射 ,但也没有用。

It's probably worth mentioning that calling world.drawDebugWorld(); 可能值得一提的是调用world.drawDebugWorld(); draws wireframes of all the objects where they would be expected to be, so now I'm suspecting the error lies in the contact listener or maybe the flags I'm using (though I haven't had any luck with any other collision flags). 在期望的所有对象上绘制线框,因此现在我怀疑错误在于联系人监听器或我正在使用的标志(尽管我与其他任何碰撞标志都没有运气) 。 Am I missing something in the contact listener? 我是否在联系侦听器中缺少某些内容?

Also, I tried using a ContactCache instead of a ContactListener but that didn't work either. 另外,我尝试使用ContactCache代替ContactListener但是那也不起作用。 Most reading I can find on the matter talks about ContactListener so I'm probably better off using that. 我在此事上能找到的大多数读物都是关于ContactListener所以我最好还是使用它。

I'm obviously forgetting something since other people are able to do this, can anyone point out what that might be? 我显然忘记了某些东西,因为其他人也可以这样做,有人能指出那是什么吗?

You are mixing collision flags ( btCollisionObject#setCollisionFlags(int *flags*) ) and collision filtering ( btCollisionWorld#addCollisionObject(object, short *group*, short *mask*) ). 您正在混合碰撞标志( btCollisionObject#setCollisionFlags(int *flags*) )和碰撞过滤btCollisionWorld#addCollisionObject(object, short *group*, short *mask*) )。 These are two very different things. 这是两件事。

You should not call the btCollisionObject#setCollisionFlags(int) method with anything other than the available flags (see here ). 应该叫btCollisionObject#setCollisionFlags(int)有什么比可用标志等(参见方法在这里 )。 The CF_CUSTOM_MATERIAL_CALLBACK collision flag must be set for the ContactListener#onContactAdded method to be called. 必须为要调用的ContactListener#onContactAdded方法设置 CF_CUSTOM_MATERIAL_CALLBACK冲突标志。 So that's why your code doesn't work as you expected. 这就是为什么您的代码无法按预期工作的原因。

Note that in my tutorial you are referring to, this is explained as well: 请注意,在我所指的教程中,也对此进行了说明

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. 在spawn方法中,我们使用setUserValue方法将此值设置为instances数组中对象的索引。 And we also inform Bullet that we want to receive collision events for this object by adding the CF_CUSTOM_MATERIAL_CALLBACK flag. 并且我们还通过添加CF_CUSTOM_MATERIAL_CALLBACK标志来通知Bullet我们要接收该对象的碰撞事件。 This flag is required for the onContactAdded method to be called. 要调用onContactAdded方法,此标志是必需的。

There is no reason to use 1<<11 instead of 1<<9 for collision filtering . 没有必要使用1<<11而不是1<<9进行冲突过滤 You probably changed something else (eg the collision flag) as well and wrongfully assumed that this change in the collision filter caused it to start working. 您可能还更改了其他内容(例如,冲突标志),并错误地认为冲突过滤器中的这一更改导致它开始工作。

Note that besides collision flags and collision filtering, there is also the (libgdx specific) contact callback filtering (explained in the second part of that tutorial). 请注意,除了冲突标志和冲突过滤之外,还有(特定于libgdx的) 联系人回调过滤 (在该教程的第二部分中进行了说明)。 Keep in mind that those are three totally different and unrelated things. 请记住,这是三个完全不同且无关的事物。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM