LibGDX - Bullet - 3D 碰撞检测未检测到碰撞
LibGDX - Bullet - 3D collision detection not detecting collisions
我正在尝试使用 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 单位球体应该会引起碰撞,不是吗?控制台中没有显示任何内容 window.
我有点怀疑我忘记了一些基本的东西,因为我试图做一个 raycast 但它也不起作用。
可能值得一提的是,调用 world.drawDebugWorld();
绘制了所有对象的线框,它们应该在它们所在的位置,所以现在我怀疑错误出在联系侦听器或我正在标记的标志上使用(虽然我没有任何其他碰撞标志的运气)。我在联系监听器中遗漏了什么吗?
此外,我尝试使用 ContactCache
而不是 ContactListener
,但这也不起作用。我能找到的关于此事的大部分阅读都是关于 ContactListener
的,所以我最好还是使用它。
我显然忘记了一些事情,因为其他人也能做到这一点,谁能指出那可能是什么?
您正在混合使用碰撞标志 (btCollisionObject#setCollisionFlags(int *flags*)
) 和碰撞 过滤 (btCollisionWorld#addCollisionObject(object, short *group*, short *mask*)
)。这是两个截然不同的东西。
你应该不调用btCollisionObject#setCollisionFlags(int)
方法时使用可用标志以外的任何东西(参见here). The CF_CUSTOM_MATERIAL_CALLBACK
collision flag 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 (explained in the second part)。请记住,这是三件完全不同且不相关的事情。
我正在尝试使用 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 单位球体应该会引起碰撞,不是吗?控制台中没有显示任何内容 window.
我有点怀疑我忘记了一些基本的东西,因为我试图做一个 raycast 但它也不起作用。
可能值得一提的是,调用 world.drawDebugWorld();
绘制了所有对象的线框,它们应该在它们所在的位置,所以现在我怀疑错误出在联系侦听器或我正在标记的标志上使用(虽然我没有任何其他碰撞标志的运气)。我在联系监听器中遗漏了什么吗?
此外,我尝试使用 ContactCache
而不是 ContactListener
,但这也不起作用。我能找到的关于此事的大部分阅读都是关于 ContactListener
的,所以我最好还是使用它。
我显然忘记了一些事情,因为其他人也能做到这一点,谁能指出那可能是什么?
您正在混合使用碰撞标志 (btCollisionObject#setCollisionFlags(int *flags*)
) 和碰撞 过滤 (btCollisionWorld#addCollisionObject(object, short *group*, short *mask*)
)。这是两个截然不同的东西。
你应该不调用btCollisionObject#setCollisionFlags(int)
方法时使用可用标志以外的任何东西(参见here). The CF_CUSTOM_MATERIAL_CALLBACK
collision flag 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 theCF_CUSTOM_MATERIAL_CALLBACK
flag. This flag is required for theonContactAdded
method to be called.
没有理由使用 1<<11
而不是 1<<9
进行碰撞 过滤 。您可能还更改了其他内容(例如碰撞标志)并错误地认为碰撞过滤器中的此更改导致它开始工作。
请注意,除了碰撞标志和碰撞过滤之外,还有该教程的(libgdx 具体)contact callback filtering (explained in the second part)。请记住,这是三件完全不同且不相关的事情。