PhysX碰撞检测之onContact和onTrigger


之前是看文档,大概知道这种用法,今天跑了下例子,记录一下

步骤

实现回调函数

PhysX总的来说有两种碰撞检测的用法

  • (1)主动:自己调用raycast、sweep以及overlap函数去检测

  • (2)被动:写回调函数,场景里面一旦发生碰撞,就会回调自己实现的函数里面,做自己的逻辑

  • PxSimulationEventCallback
    继承这个纯虚类,实现其中的两个函数

class PhysXCallback :public PxSimulationEventCallback {
public:
     PhysXCallback();
    virtual void                            onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs);
    virtual void                            onTrigger(PxTriggerPair* pairs, PxU32 count);
    virtual void                            onConstraintBreak(PxConstraintInfo*, PxU32) {}
    virtual void                            onWake(PxActor**, PxU32) {}
    virtual void                            onSleep(PxActor**, PxU32) {}
    virtual void                            onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
};
  • 注册
    把自己写的类new一个实例,丢给PxSceneDesc结构,创建物理场景的时候就等于是注册进去了
class PxSceneDesc
{
public:
    // 省略...
    /**
    \brief Possible notification callback.
    This callback will be associated with the client PX_DEFAULT_CLIENT.
    Please use PxScene::setSimulationEventCallback() to register callbacks for other clients.
    <b>Default:</b> NULL
    @see PxSimulationEventCallback PxScene.setSimulationEventCallback() PxScene.getSimulationEventCallback()
    */
    PxSimulationEventCallback*    simulationEventCallback;
    /**
    \brief Possible asynchronous callback for contact modification.
    <b>Default:</b> NULL
    @see PxContactModifyCallback PxScene.setContactModifyCallback() PxScene.getContactModifyCallback()
    */
    PxContactModifyCallback*    contactModifyCallback;
    /**
    \brief Possible asynchronous callback for contact modification.
    <b>Default:</b> NULL
    @see PxContactModifyCallback PxScene.setContactModifyCallback() PxScene.getContactModifyCallback()
    */
    PxCCDContactModifyCallback*    ccdContactModifyCallback;
            // 省略...
}

可以看到还有另外两个回调函数可以用来注册

  • PxShapeFlag::eTRIGGER_SHAPE
    只是完成上面两个,加上这个标记PxShapeFlag::eTRIGGER_SHAPE,onTrigger就算是ok了。这个标记是说一旦两个碰撞的物件,其中有一个打上了这个标记,就会触发onTrigger事件,从而可以回调到这个自己注册的函数中
shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);

struct PxPairFlag
{
    enum Enum
    {
        // 省略
        /**
        \brief Call contact report callback or trigger callback when this collision pair starts to be in contact.
        If one of the two collision objects is a trigger shape (see #PxShapeFlag::eTRIGGER_SHAPE) 
        then the trigger callback will get called as soon as the other object enters the trigger volume. 
        If none of the two collision objects is a trigger shape then the contact report callback will get 
        called when the actors of this collision pair start to be in contact.
        \note Only takes effect if the colliding actors are rigid bodies.
        \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised
        @see PxSimulationEventCallback.onContact() PxSimulationEventCallback.onTrigger()
        */
        eNOTIFY_TOUCH_FOUND                    = (1<<2),
        // 省略。。。
  • PxPairFlag
    只是完成上面两个,onContact是不会触发的,即使物体已经发生碰撞了。要想解决这个问题,需要重写FilterShader函数,并且返回的PxPairFlag要带上标记PxPairFlag::eNOTIFY_TOUCH_FOUND才行。

  • FilgerShader函数

static physx::PxFilterFlags defaultPhysX3FilterShader(
    physx::PxFilterObjectAttributes attributes0,
    physx::PxFilterData filterData0,
    physx::PxFilterObjectAttributes attributes1,
    physx::PxFilterData filterData1,
    physx::PxPairFlags &pairFlags, 
    const void * constantBlock ,
    physx::PxU32 constantBlockSize)
{
// morphe me used filter callback
    bool kinematic0 = physx::PxFilterObjectIsKinematic(attributes0);
    bool kinematic1 = physx::PxFilterObjectIsKinematic(attributes1);
    if (kinematic0 && kinematic1)
    {
        pairFlags = physx::PxPairFlags(); 
        return physx::PxFilterFlag::eSUPPRESS;
    }
    // Support the idea of this being called from a user's filter shader - i.e. don't trample on existing flags
    pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT;
    pairFlags = pairFlags | physx::PxPairFlag::eSOLVE_CONTACT
        | physx::PxPairFlag::eNOTIFY_TOUCH_FOUND
        | physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
    {
        // now test groups (word0) against ignore groups (word1)
        if ((filterData0.word0 & filterData1.word1) || (filterData1.word0 & filterData0.word1)) 
        {
            pairFlags = physx::PxPairFlags(); // disable all dynamic collisions
            return physx::PxFilterFlag::eSUPPRESS; // this stops the pair being actually passed into ray probe onObjectQuery
        }
        else
        {
            return physx::PxFilterFlag::eDEFAULT;
        }
    }
}

参考

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值