2个物体之间的子弹碰撞回调
Posted
技术标签:
【中文标题】2个物体之间的子弹碰撞回调【英文标题】:bullet collision callback between 2 bodies 【发布时间】:2013-12-16 12:39:04 【问题描述】:我有 2 个对象,一个球体和一个盒子,当其中一个与另一个碰撞时,它们会做一些动作(即摧毁盒子)。
我尝试了几种方法:
checkCollideWith 总是返回 true; contactPairTest - 这个我不明白怎么用。 它需要 3 个参数、2 个对象和一个回调。我以为回调可以是我代码中的任何函数,但它不是那样工作的。谁能举例说明当 2 个 btRigidBodies 碰撞(即 bodyA 和 bodyB)时如何调用方法,例如 CollissionResult()?
【问题讨论】:
对文档的快速检查表明,contactPairTest 需要一个类型派生自抽象类 ContactResultCallback 的对象。所以你的问题是如何做到这一点? 【参考方案1】:也许这个例子将有助于解释这个概念。您必须定义一个从现有抽象类派生的新类。您使用回调代码覆盖抽象类方法之一。然后创建派生类的对象并将其传递给要调用回调的函数。这是一种足够常见的 C++ 技术。
struct MyContactResultCallback : public ContactResultCallback
btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,
int partId0,
int index0,
const btCollisionObjectWrapper* colObj1Wrap,
int partId1,
in index1)
// your callback code here
;
MyContactResultCallback callback;
world.contactPairTest(bodyA, bodyB, callback);
我应该补充一点,我对这个库一无所知。我刚刚阅读了文档。
编辑
展示如何将上下文成员添加到MyContactResultCallback
。
struct MyContactResultCallback : public ContactResultCallback
MyContactResultCallback(some_type* ptr) : context(ptr)
btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,
int partId0,
int index0,
const btCollisionObjectWrapper* colObj1Wrap,
int partId1,
in index1)
context->currentPoints += 10;
some_type* context;
;
MyContactResultCallback callback(ptr_to_some_object);
world.contactPairTest(bodyA, bodyB, callback);
ptr_to_some_object
是指向您要递增的具有currentPoints
的对象的指针。我不知道那是什么类型的对象,所以我刚才说some_type
,你可以用任何真正的类型替换它。
这是使用对象作为回调而不是函数的要点。如果回调是一个对象,您可以将数据成员添加到您想要的任何目的,您不能对函数执行此操作。
【讨论】:
你好。谢谢回复。我已经尝试了您的示例,然后创建了一个 myContactResultCallback 对象MyContactResultCallback callback;
,然后调用了contactPairTest 方法bt_dynamicsWorld->contactPairTest(bodyA, bodyB, callback);
。运行导致报错说addSingleResult需要返回一个值,所以我加了return 0;
。这允许程序运行,但是当我碰撞 2 个对象时,没有调用回调(2 个对象显然在反弹时碰撞)
@b0Gd4N 好吧,恐怕我已经尽可能地帮助了你(即使用 C++ 语法)。正如我所说,我根本不知道这个库。
它不起作用的原因是我忘记将collisionFlags
添加到两个对象中。所以现在我有 2 个对象碰撞并调用回调,但是我遇到了另一个问题:在评论 // your callback code here
之后,我有一个报告碰撞的输出,它可以工作。在此之后,我想增加一个在头文件中声明为公共的变量,因此它应该可以在任何地方访问。但是当我写currentPoints += 10
时,我收到一个错误a nonstatic member reference must be relative to a specific object
。我怎样才能通过这个?
@b0Gd4N 这就是将回调作为对象的美妙之处。添加指向MyContactResultCallback
结构的指针。指针指向具有要递增的变量的对象。然后您可以使用该指针从MyContactResultCallback::addSingleResult
内部执行增量
我一直在努力制作这个指针一段时间。我尝试向 addSingleResult 方法添加另一个参数,但是当我创建结构的实例时,我收到错误 addSingleResult is not overridable
。我真的不明白我必须按照你说的去做。【参考方案2】:
我发现最简单的方法是检查歧管。如果您只询问dispatcher,则无需自定义类。
每次踏入世界后都执行这个:
btDispatcher* dp = world->getDispatcher();
const int numManifolds = dp->getNumManifolds();
for ( int m=0; m<numManifolds; ++m )
btPersistentManifold* man = dp->getManifoldByIndexInternal( m );
const btRigidBody* obA = static_cast<const btRigidBody*>(man->getBody0());
const btRigidBody* obB = static_cast<const btRigidBody*>(man->getBody1());
const void* ptrA = obA->getUserPointer();
const void* ptrB = obB->getUserPointer();
// use user pointers to determine if objects are eligible for destruction.
...
const int numc = man->getNumContacts();
float totalImpact = 0.0f;
for ( int c=0; c<numc; ++c )
totalImpact += man->getContactPoint(c).m_appliedImpulse;
if ( totalImpact > threshold )
// Here you can break one, or both shapes, if so desired.
【讨论】:
以上是关于2个物体之间的子弹碰撞回调的主要内容,如果未能解决你的问题,请参考以下文章