C++ Bullet Physics 最简单的碰撞示例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11175694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bullet Physics Simplest Collision Example
提问by Aztal
I'm trying to use Bullet Physics for collision detection only. I don't need it to move any objects for me or handle rendering with callbacks. I just want to update object locations every frame and use it to tell me when I have collisions. To get the simplest example going, I'm trying to find collisions between objects with btBoxShape as their shape. Everything runs fine without crashes or apparent memory leaks, but I get no collisions so I must be making some mistakes somewhere. I'll try to keep this as brief as I can without leaving anything important out.
我正在尝试仅将 Bullet Physics 用于碰撞检测。我不需要它来为我移动任何对象或使用回调处理渲染。我只想更新每一帧的对象位置,并在发生碰撞时使用它来告诉我。为了获得最简单的示例,我试图找到以 btBoxShape 作为其形状的对象之间的碰撞。一切都运行良好,没有崩溃或明显的内存泄漏,但我没有遇到冲突,所以我一定是在某处犯了一些错误。我会尽量保持简短,不遗漏任何重要的内容。
Here's my world setup function:
这是我的世界设置功能:
collisionConfig = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfig);
overlappingPairCache = new btDbvtBroadphase();
solver = new btSequentialImpulseConstraintSolver;
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,
overlappingPairCache, solver, collisionConfig);
dynamicsWorld->setGravity(btVector3(0.0f, -9.8f, 0.0f));
Right now I have player and enemy objects of the type btCollisionObject*. I'm setting them up like this:
现在我有 btCollisionObject* 类型的玩家和敌人对象。我是这样设置的:
mPlayerBox = new btBoxShape(btVector3(1,3,1));
mPlayerObject = new btCollisionObject();
mPlayerObject->setCollisionShape(mPlayerBox);
btTransform playerWorld;
playerWorld.setIdentity();
//playerPos is a D3DXVECTOR3 that holds the camera position.
playerWorld.setOrigin(btVector3(playerPos.x, playerPos.y, playerPos.z));
mPlayerObject->setWorldTransform(playerWorld);
mPlayerObject->forceActivationState(DISABLE_DEACTIVATION);//maybe not needed
dynamicsWorld->addCollisionObject(mPlayerObject);
I do essentially the same thing with my enemy objects.
我对我的敌人对象做了基本相同的事情。
Then every frame I update all my objects with something like this:
然后每一帧我都用这样的东西更新我的所有对象:
btTransform updatedWorld;
updatedWorld.setIdentity();
updatedWorld.setOrigin(btVector3(position.x, position.y, position.z));
mPlayerObject->setWorldTransform(updatedWorld);
//do the same for my enemies, and then...
dynamicsWorld->performDiscreteCollisionDetection();
//Also tried doing this with stepSimulation(deltaTime, 7), but nothing changed.
//stepSimulation seems to only be for letting Bullet set world Transforms?
//check collisions with player
dynamicsWorld->contactTest(mPlayerObject, resultCallback);
int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
if(numManifolds > 0)
{
//there's a collision, execute blah blah blah
}
And finally, here's the structure that defines my result callback:
最后,这是定义我的结果回调的结构:
struct rCallBack : public btCollisionWorld::ContactResultCallback
{
btScalar rCallback::addSingleResult(btManifoldPoint& cp, const btCollisionObject*
colObj0, int partId0, int index0, const btCollisionObject* colObj1, int partId1,
int index1)
{
btVector3 ptA = cp.getPositionWorldOnA();
btVector3 ptB = cp.getPositionWorldOnB();
return 0;
}
}
I've looked at a lot of the demos, but they seem to mostly be leaving the movement up to Bullet, and since I'm moving characters at a set speed without any special physics when they collide, I had trouble adapting the examples into my application. The result callback actually came from this post on the forums: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6816It's about using triangle meshes, but it seemed closest to what I was trying to implement.
我看过很多演示,但他们似乎主要将运动留给 Bullet,而且由于我以设定的速度移动角色,当他们碰撞时没有任何特殊的物理,我很难将这些例子改编成我的应用程序。结果回调实际上来自论坛上的这篇文章:http: //bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6816这是关于使用三角形网格,但它似乎最接近我试图实现的。
Anyway, if you read this far, thank you!! Any advice or links you could spare would be very much appreciated.
无论如何,如果你读到这里,谢谢你!!非常感谢您可以提供的任何建议或链接。
回答by John Chui
I am writing an IOS app with flighter shooting each other on 3D scene. I use bullet physics for collision detection I set the flighter as kinematic object, my logic move the flighter and then update the btMotionState worldTransform of the kinematic object. I also don't get any collision detections until i change the following two statements (set the masking and group to the same for both player and enemy)
我正在编写一个 IOS 应用程序,其中飞行器在 3D 场景中相互射击。我使用子弹物理进行碰撞检测我将飞行器设置为运动学对象,我的逻辑移动飞行器,然后更新运动学对象的 btMotionState worldTransform。在我更改以下两个语句之前,我也没有得到任何碰撞检测(将玩家和敌人的掩蔽和组设置为相同)
dynamicsWorld->addRigidBody(mPlayerObject,1,1);
dynamicsWorld->addRigidBody(mEnemyObject,1,1);
...
dynamicsWorld->setInternalTickCallback(myTickCallback);
then i can see the
然后我可以看到
void myTickCallback(btDynamicsWorld *world, btScalar timeStep) {
int numManifolds = world->getDispatcher()->getNumManifolds();
printf("numManifolds = %d\n",numManifolds);
}
numManifolds value become 1 when object collides.
当对象发生碰撞时,numManifolds 值变为 1。
回答by franzbischoff
You can check the contact information as explained here:
您可以按照此处的说明检查联系信息:
Contact Information
联系信息
The best way to determine if collisions happened between existing objects in the world, is to iterate over all contact manifolds. This should be done during a simulation tick (substep) callback, because contacts might be added and removed during several substeps of a single stepSimulation call. A contact manifold is a cache that contains all contact points between pairs of collision objects. A good way is to iterate over all pairs of objects in the entire collision/dynamics world:
确定世界中现有对象之间是否发生碰撞的最佳方法是迭代所有接触流形。这应该在模拟滴答(子步)回调期间完成,因为在单个 stepSimulation 调用的几个子步中可能会添加和删除联系人。接触流形是一个缓存,其中包含成对碰撞对象之间的所有接触点。一个好方法是迭代整个碰撞/动力学世界中的所有对象对:
//Assume world->stepSimulation or world->performDiscreteCollisionDetection has been called
int numManifolds = world->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++)
{
btPersistentManifold* contactManifold = world->getDispatcher()->getManifoldByIndexInternal(i);
btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
int numContacts = contactManifold->getNumContacts();
for (int j=0;j<numContacts;j++)
{
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance()<0.f)
{
const btVector3& ptA = pt.getPositionWorldOnA();
const btVector3& ptB = pt.getPositionWorldOnB();
const btVector3& normalOnB = pt.m_normalWorldOnB;
}
}
}
You may be interested in btGhostObject that keeps track of its own overlapping pairs.
您可能对跟踪自己重叠对的 btGhostObject 感兴趣。