判断位置是否会发生碰撞
程序员文章站
2024-03-16 15:38:40
...
核心函数整理
physx的函数解释在下面。
// 从actor中获取第一个shape
PxShape * getShapeByActor(PxRigidActor *actor)
{
if (!actor)
return NULL;
const PxU32 numShapes = actor->getNbShapes();
if (numShapes <= 0) {
cout << "test Shape num is <= 0" << endl;
return NULL;
}
PxShape* shape = NULL;
actor->getShapes(&shape, 1);
return shape;
}
// 参数 out [depth] : 获取嵌入的深度
// 此处的targetActor可以换成transform和geometry
int testComputePenetration(const PxTransform &pole, const PxGeometry & geom, PxRigidActor * targetActor, PxF32 &depth)
{
PxShape* shape = getShapeByActor(actor);
if (!shape) {
return -1;
}
PxTransform targetPole = actor->getGlobalPose();
PxGeometry &targetGeometry = shape->getGeometry().any();
// 如果不支持,强行调用,程序会崩溃的,所以一定要判断
if (geom.getType() == PxGeometryType::Enum::eTRIANGLEMESH) {
cout << "physx is not support, it one geometry only support box, sphere, capsule or convex, and other geometry may be of any type" << endl;
return -1;
}
PxVec3 direction(0);
// 判断两个形状是否内嵌(碰撞), 并获取深度和方向
bool isOverlapping = PxGeometryQuery::computePenetration(direction,
depth,
geom,
pole,
targetGeometry,
targetPole
);
cout << "testComputePenetration isOverlapping:" << isOverlapping << endl;
if (isOverlapping) {
cout << "depth is :" << depth << endl;
cout << "direction is : x = " << direction.x << " y = " << direction.y << " z = " << direction.z << endl;
}
return isOverlapping;
}
// 参数 in [trans] : 检测的位置
// 参数 in [geom] : 检测的形状
// 不使用bool是因为了返回值可以判断是错误 还是出现了不碰撞,不然无法区分
int testOverlapBySence(PxScene * scene, const PxTransform &trans, const PxGeometry & geom)
{
int ret = 0;
// 如果不支持,强行调用,程序会崩溃的,所以一定要判断
if (geom.getType() == PxGeometryType::Enum::eTRIANGLEMESH) {
cout << "physx is not support, it one geometry only support box, sphere, capsule or convex, and other geometry may be of any type" << endl;
return -1;
}
PxF32 depth = 0;
const PxU32 bufferSize = 256; // [in] size of 'hitBuffer'
PxOverlapHit hitBuffer[bufferSize]; // [out] User provided buffer for results
// PxQueryFilterData() 默认设置 filterdata.flag = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC
PxQueryFilterData filterdata = PxQueryFilterData();
//filterdata.data = collisionGroup; // 设置值允许打了碰撞组标的shape可以与ray出现碰撞
// 获取场景的多个碰撞结果,可以使用过滤
PxI32 num = PxSceneQueryExt::overlapMultiple(*scene,
geom,
trans,
hitBuffer,
bufferSize * sizeof(PxOverlapHit),
filterdata
);
for (PxU32 i = 0; i < num; i++){
PxOverlapHit *tmpHitInfo = &hitBuffer[i];
tmpHitInfo->actor;
if(0 < testComputePenetration(trans, geom, tmpHitInfo->actor, depth)){
// 碰撞有可能是相交或者相切,需要判断depth是否在自己的接受范围内,因为有可能是0.000001这种。
// 如果depth超出相切的接受范围,可认为是相交,可直接范围结果了
if(depth > 0.000001)
return 2; // 相交
}
}
cout << "num is :" << num << endl;
if(num > 0)
return 1; // 相切
return 0; // 无碰撞
}
获取位置是否会碰撞
-
有三种方法获取碰撞,但是无法获取深度。
-
由于这三种方法只能获取碰撞,所以可以通过这几种方法,先获取相碰撞的actor,然后在单独计算碰撞的深度,即可获取到是相交还是相切。
-
但是该方法有个问题,这三种获取碰撞的方法,获取到碰撞的actor,拿到计算深度的那个api中计算,有可能得到的是非碰撞。通过测试调查,是因为两个geom之间有非常微小的缝隙,似乎是因为精度引起的。所以我认为如果获取到碰撞,但是获取深度的api认为没有碰撞,即可判断为是相切。如果计算得到的深度也在可接受范围内,也可以认为相切,反之是相交的情况。
-
使用方法分别如下
方法一:
const PxU32 bufferSize = 256; // [in] size of 'hitBuffer'
PxOverlapHit hitBuffer[bufferSize]; // [out] User provided buffer for results
PxOverlapBuffer buf(hitBuffer, bufferSize); // [out] Blocking and touching hits stored here
// PxQueryFilterData() 默认设置 filterdata.flag = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC
PxQueryFilterData filterdata = PxQueryFilterData(); // 和raycast的过滤一样
// 获取场景的所有碰撞
bool hadBlockingHit = scene->overlap(geom, trans, buf, filterdata);
for (PxU32 i = 0; i < buf.nbTouches; i++)
{
//buf.touches[i];// 该数据是PxOverlapHit类型,可直接获取到碰撞actor
printf("actor addr : %p\n", buf.touches[i].actor);
}
cout << "hadBlockingHit:" << hadBlockingHit << endl;
cout << "buf.nbTouches : " << buf.nbTouches << endl;
方法二:
const PxU32 bufferSize = 256; // [in] size of 'hitBuffer'
PxOverlapHit hitBuffer[bufferSize]; // [out] User provided buffer for results
// PxQueryFilterData() 默认设置 filterdata.flag = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC
PxQueryFilterData filterdata = PxQueryFilterData(); // 和raycast的过滤一样
// 获取场景的所有碰撞
PxI32 num = PxSceneQueryExt::overlapMultiple(*scene,
geom,
trans,
hitBuffer,
bufferSize * sizeof(PxOverlapHit),
filterdata
);
// 循环遍历所有碰撞
for (PxU32 i = 0; i < num; i++){
PxOverlapHit *tmpHit = &hitBuffer[i];
}
cout << "num is :" << num << endl;
方法三:该方法获取到任一个碰撞
PxQueryFilterData filterdata = PxQueryFilterData(); // 和raycast的过滤一样
PxOverlapHit hit;
bool isover = PxSceneQueryExt::overlapAny(*scene,
geom,
trans,
hit,
filterdata
);
cout << "isover:" << isover << endl;
if (isover) {
}
获取到是否碰撞,并获取嵌入深度和方向
// 参数 out [depth] : 获取嵌入的深度
// 此处的targetActor可以换成位置和形状
PxF32 depth = 0;
PxVec3 direction(0);
// 判断两个形状是否内嵌(碰撞), 并获取深度和方向
bool isOverlapping = PxGeometryQuery::computePenetration(direction,
depth,
geom,
pole,
targetGeometry,
targetPole
);
cout << "ComputePenetration isOverlapping:" << isOverlapping << endl;
if (isOverlapping) {
cout << "depth is :" << depth << endl;
cout << "direction is : x = " << direction.x << " y = " << direction.y << " z = " << direction.z << endl;
}
上一篇: 数据结构-散列表
下一篇: 重学数据结构与算法——汉诺塔
推荐阅读
-
判断位置是否会发生碰撞
-
cocos2d-x 判断圆形是否与矩形发生物理碰撞
-
android 判断 手机 是否 打开 允许模拟位置 选项 博客分类: android android允许模拟位置
-
visio二次开发--判断文档是否已发生变化(变化就加星号*)
-
读一个数,判断这个数是否在数组中并找出所在的位置
-
JQuery使用mousedown和mouseup判断鼠标按下与释放位置是否相同
-
visio二次开发--判断文档是否已发生变化(变化就加星号*)
-
Android实现判断位置信息是否开启以及开启位置信息功能
-
定位地理位置PHP判断员工打卡签到经纬度是否在打卡之内
-
通过实例判断mysql update是否会锁表