physx中判断actor是否会发生碰撞
程序员文章站
2024-03-16 15:43:52
...
一、物理碰撞模拟方法
通过模拟一个真实的碰撞,但是不体现碰撞的特性,通过回调的方式来获取到对应的actor的指针来判断是否碰撞,但是要忽略掉当前的碰撞。
-
设置分类
const PxFilterData collisionGroupIgnore(0, 0, 0, 1); // 分类自己怎么定义都可以
-
设置形状shape中的分类,方便在filtershape函数中做过滤
PxRigidDynamic* createIgnoreDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity = PxVec3(0)) { PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f); dynamic->userData = new int; int shapeNb = dynamic->getNbShapes(); cout << "shapeNb:" << shapeNb << endl; PxShape * shape = nullptr; dynamic->getShapes(&shape, 1); if (shape) { cout << "shape is not null" << endl; // 设置shape的FilterData,用在filtershape做匹配 shape->setSimulationFilterData(collisionGroupIgnore); } else { cout << "shape is null" << endl; } memcpy(dynamic->userData, &userid, sizeof(int)); userid++; // 场景中添加零件 gScene->addActor(*dynamic); return dynamic; }
-
设置filterShader的回调,从此处可以获取到碰撞的actor,返回值设置PxFilterFlag::eKILL即可放弃此次碰撞。
class ContactFilterCallback : public PxSimulationFilterCallback { public: virtual PxFilterFlags pairFound( PxU32 pairID, PxFilterObjectAttributes attributes0, PxFilterData filterData0, const PxActor* a0, const PxShape* s0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, const PxActor* a1, const PxShape* s1, PxPairFlags& pairFlags) override { cout << "pairFound !!!!!!!!!" << endl; cout << "pairFound actor0:" << *(int *)(a0->userData) << " actor1:" << *(int *)(a1->userData) << endl; //return PxFilterFlag::eKILL; // 将该碰撞事件丢弃,此时就没有碰撞效果了 return PxFilterFlag::eSUPPRESS; // 对象的边界体积重叠,或者直到其中一个碰撞对象的过滤相关数据发生更改,就忽略该碰撞对 } virtual void pairLost(PxU32 pairID, PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, bool objectRemoved) override { } virtual bool statusChange(PxU32& pairID, PxPairFlags& pairFlags, PxFilterFlags& filterFlags) override { return false; } }; ContactFilterCallback gContactFilterCallback;
-
设置场景过滤条件函数
在场景配置中设置过滤函数:
sceneDesc.filterShader = filterShader;
static PxFilterFlags filterShader( PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize) { // 默认对所有为过滤的碰撞产生默认回调 pairFlags = PxPairFlag::eCONTACT_DEFAULT; pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND; // 普通的触碰,调用回调 if (filterData0 == collisionGroupIgnore || filterData1 == collisionGroupIgnore) { cout << "filterShader this is ignore shape" << endl; return PxFilterFlag::eCALLBACK; // 调用filterShader的回调 } pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT; // 检测到CCD碰撞的时候 pairFlags |= PxPairFlag::eNOTIFY_TOUCH_CCD; // 触碰且CCD,调用回调 pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND; // 普通的触碰,调用回调 return PxFilterFlag::eDEFAULT; }
-
设置场景过滤函数的回调
sceneDesc.filterCallback = &gContactFilterCallback;
-
运行调试即可
二、通过Geometry和Tranform来判断是否会出现碰撞
在physx中,有通过geometry+transform的api来获取两个几何体是否出现内嵌,我们可以通过这种方式来获取两个actor是否回发生碰撞。
physx里面有两种,一种只判断内嵌,一种是判断内嵌的深度,api分别如下
// 判断是否内嵌
bool PxGeometryQuery::overlap(const PxGeometry & geom0,
const PxTransform & pose0,
const PxGeometry & geom1,
const PxTransform & pose1
);
// 判断是否内嵌,并求出内嵌深度
bool PxGeometryQuery::computePenetration ( PxVec3 & direction,
PxF32 & depth,
const PxGeometry & geom0,
const PxTransform & pose0,
const PxGeometry & geom1,
const PxTransform & pose1
)
调用方式如下
int myOverlap(PxRigidActor * actor, PxGeometry &geom, PxTransform &trans)
{
if (!actor) {
cout << "actor is null" << endl;
return -1;
}
bool isOverlapping = false;
PxTransform pole = actor->getGlobalPose();
const PxU32 numShapes = actor->getNbShapes();
if (numShapes <= 0){
cout << "Shape num is <= 0" << endl;
return -1;
}
PxShape** shapes = (PxShape**)malloc(sizeof(PxShape*)*numShapes);
actor->getShapes(shapes, numShapes);
for (PxU32 i = 0; i < numShapes; i++)
{
PxShape* shape = shapes[i];
cout << "shape[" << i << "]:" << shape->getGeometryType() << endl;;
PxGeometry &geometry = shape->getGeometry().any();
isOverlapping = PxGeometryQuery::overlap(geometry, pole, geom, trans);
if (isOverlapping) {
cout << "myOverlap isOverlapping:" << isOverlapping << endl;
break;
}
cout << "myOverlap isOverlapping:" << isOverlapping << endl;
}
free(shapes);
return isOverlapping;
}
int myOverlap(PxRigidActor * actor0, PxRigidActor * actor1)
{
if (!actor0 || !actor1) {
cout << "actor is null" << endl;
return -1;
}
PxTransform pole0 = actor0->getGlobalPose();
PxTransform pole1 = actor1->getGlobalPose();
const PxU32 numShapes0 = actor0->getNbShapes();
const PxU32 numShapes1 = actor1->getNbShapes();
if (numShapes0 <= 0 || numShapes1 <= 0) {
cout << "test Shape num is <= 0" << endl;
return -1;
}
PxShape* shapes0 = NULL;
actor->getShapes(&shapes0, 1);
PxShape* shapes1 = NULL;
actor->getShapes(&shapes1, 1);
PxGeometry &geometry0 = shapes0->getGeometry().any();
PxGeometry &geometry1 = shapes1->getGeometry().any();
bool isOverlapping = PxGeometryQuery::overlap(geometry0, pole0, geometry1, pole1);
cout << "testShapeGetGeometry isOverlapping:" << isOverlapping << endl;
return isOverlapping;
}
上一篇: 数据结构与算法_汉诺塔
下一篇: 数据结构7:汉诺塔算法
推荐阅读