LibGDX - Bullet - 3D обнаружение столкновений не обнаруживает столкновения - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь провести 3D-тест столкновения с Bullet, который, как я ожидал, сработает довольно просто:

@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;
    }
}

(я следовал этому руководству, хотя я, очевидно, немного отклонился от него, чтобы попытаться сделать его еще проще.)

Сфера из 2,5 единиц в (0, 0, 0) и сфера из 2,5 единиц в (1, 0, 0) должны вызывать столкновение, не так ли? В окне консоли ничего не появляется.

Я несколько подозреваю, что есть кое-что фундаментальное, что я забыл, так как я пытался сделать raycast , и это тоже не работает.

Вероятно, стоит упомянуть, что вызов world.drawDebugWorld(); рисует каркас всех объектов, где они должны быть, так что теперь я подозреваю, что ошибка заключается в приемнике контактов или, возможно, используемых мной флагах (хотя я не повезло с другими флагами столкновений). Я что-то упустил в контактном слушателе?

Кроме того, я попытался использовать ContactCache вместо ContactListener, но это тоже не сработало. В большинстве книг, которые я могу найти по этому вопросу, говорится о ContactListener, поэтому мне, вероятно, лучше использовать это.

Я, очевидно, что-то забываю, так как другие люди могут сделать это, кто-нибудь может указать, что это может быть?

1 Ответ

0 голосов
/ 13 мая 2018

Вы смешиваете флаги столкновения (btCollisionObject#setCollisionFlags(int *flags*)) и фильтрацию столкновений (btCollisionWorld#addCollisionObject(object, short *group*, short *mask*)). Это две очень разные вещи.

Вы должны не вызывать метод btCollisionObject#setCollisionFlags(int) с чем-либо, кроме доступных флагов (см. здесь ). флаг столкновения *1013* должен быть установлен для вызова метода ContactListener#onContactAdded. Вот почему ваш код работает не так, как вы ожидали.

Обратите внимание, что в моем уроке вы ссылаетесь на , это также объясняется :

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

В методе spawn мы устанавливаем это значение, используя метод setUserValue, для индекса объекта в массиве instance. И мы также сообщаем Bullet, что мы хотим получать события столкновения для этого объекта, добавив флаг CF_CUSTOM_MATERIAL_CALLBACK. Этот флаг необходим для вызова метода onContactAdded.

Нет смысла использовать 1<<11 вместо 1<<9 для коллизии фильтрации . Вы, вероятно, также изменили что-то другое (например, флаг столкновения) и ошибочно предположили, что это изменение в фильтре столкновений заставило его начать работать.

Обратите внимание, что помимо флагов коллизий и фильтрации коллизий, есть также (специфичная для libgdx) фильтрация обратных вызовов (объяснено во второй части этого урока). Имейте в виду, что это три совершенно разные и не связанные вещи.

...