欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

判断位置是否会发生碰撞

程序员文章站 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;
}

相关标签: physx c/c++ physx