前面的两篇中,我们介绍了 PhysX 3.2中场景查询的一些基本概念,以及查询中如何设置过滤。有了前两节做的准备,到这一节中,我们就具体看看各种场景查询该如何使用。
首先看单次执行的查询。之前我们提到过,单次执行的查询,有查询有无的*Any方式,还有查询最近的*Single方式,和查询所有的*Multiple方式。
所有的这些查询方式,从根本上讲,可以抽象为从一个位置,投射一个或者一组形体一定的距离, 查询跟物理场景中物体的交互情况;对于Raycast,可以理解为投射的形体就是一个点;对于Overlap,可以理解为投射的距离是0;同时,只有Sweep支持多个形体组成一组来查询的方式。
以上面加粗的字体为关键字作为基本的查询条件,再加上过滤和返回值选择的参数,以及其他加快查询的便利设计,我们可以很方便的理解各种查询的API。以raycastSingle,sweepMultiple和OverlapAny为例来说明:
bool raycastSingle(
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, //基本查询条件
PxSceneQueryFlags outputFlags, //定义返回的数据
PxRaycastHit& hit, //返回查询结果,*single类,返回一个结果
const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), //过滤条件
PxSceneQueryFilterCallback* filterCall = NULL, //过滤条件
const PxSceneQueryCache* cache = NULL, //快查Cache
PxClientID queryClient = PX_DEFAULT_CLIENT) const; //SDK的一个实验特性,可暂不考虑
PxI32 sweepMultiple( const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
PxSceneQueryFlags outputFlags,
PxSweepHit* hitBuffer, //查询结果返回缓冲区,*multiple类,返回多个结果
PxU32 hitBufferSize, //查询结果缓冲区的大小
bool& blockingHit, //返回结果中是否有Blocking Hit
const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(),
PxSceneQueryFilterCallback* filterCall = NULL,
const PxSceneQueryCache* cache = NULL,
PxClientID queryClient = PX_DEFAULT_CLIENT,
const PxReal inflation = 0.f) const; //如果需要,将geometry增肥一点
PxI32 sweepMultiple(const PxGeometry** geometryList, const PxTransform* poseList, //Sweep查询支持多个geometry组成一个整体来查询
const PxFilterData* filterDataList, PxU32 geometryCount,
const PxVec3& unitDir, const PxReal distance,
PxSceneQueryFlags outputFlags,
PxSweepHit* hitBuffer,
PxU32 hitBufferSize,
bool& blockingHit,
PxSceneQueryFilterFlags filterFlags = PxSceneQueryFilterFlag::eDYNAMIC | PxSceneQueryFilterFlag::eSTATIC,
PxSceneQueryFilterCallback* filterCall = NULL,
const PxSceneQueryCache* cache = NULL,
PxClientID queryClient = PX_DEFAULT_CLIENT,
const PxReal inflation = 0.f) const;
bool overlapAny(const PxGeometry& geometry, const PxTransform& pose,
PxShape*& hit, //*Any类查询,最快的速度返回跟谁碰上了,返回的数据是默认的
const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(),
PxSceneQueryFilterCallback* filterCall = NULL,
PxClientID queryClient = PX_DEFAULT_CLIENT) const;
下面,就用raySingle为例来简单看该如何调用查询函数:
PxScene* scene;
PxVec3 origin = ...; // [in] 射线起点
PxVec3 unitDir = ...; // [in] 标准化的射线方向
PxReal maxDistance = ...; // [in] 投射的距离
PxRaycastHit hit; // [out] 检测结果
// [in] 定义我们需要的返回数据
const PxSceneQueryFlags outputFlags = PxSceneQueryFlag::eDISTANCE | PxSceneQueryFlag::eIMPACT | PxSceneQueryFlag::eNORMAL;
// 采用默认的过滤,即不过滤,返回结果保存到hit中返回
bool status = scene->raycastSingle(origin, unitDir, maxDistance, outputFlags, hit);
------------------------------------------------------------------
上面,我们介绍的是单次查询的API和使用,下面,我们说说SDK提供的另一种查询方式,批处理查询,PxBatchQuery。
批处理查询的方式,简单来说,可以这么理解:批处理的组织、执行以及结果的处理,都通过PxBatchQuery对象来进行;具体执行的过程,则是先定义好收结果的空间,然后按需将需要的查询增加到Batch中,在收集需求完毕后,调用PxBatchQuery的execute执行所有的查询。
我们可以从下面从PhysX SDK 3.2 Sample中抽取出来的代码中更清楚的了解该如何使用:
// 准备接收结果的缓冲区,创建PxBatchQuery
PxBatchQueryDesc batchQueryDesc;
batchQueryDesc.userRaycastResultBuffer = mRayCastResults;
batchQueryDesc.userRaycastHitBuffer = mRayCastHits;
batchQueryDesc.raycastHitBufferSize = mHitSize;
mBatchQuery = mSampleSubmarine.getActiveScene().createBatchQuery(batchQueryDesc);
// 收集查询请求
mSqRayBuffer->mBatchQuery->raycastSingle(rayStart, crabToSub.getNormalized(), rayDist, PxSceneQueryFilterFlag::eSTATIC|PxSceneQueryFilterFlag::eDYNAMIC);
//...
mSqRayBuffer->mBatchQuery->raycastSingle(rayStart[j], rayDir, rayDist, PxSceneQueryFilterFlag::eSTATIC|PxSceneQueryFilterFlag::eDYNAMIC);
//...
// 执行查询
mSqRayBuffer->mBatchQuery->execute();
// 处理查询结果
for(PxU32 i = 0; i < mSqRayBuffer->mQueryResultSize; i++)
{
PxRaycastQueryResult& result = mSqRayBuffer->mRayCastResults[i];
if(result.queryStatus == PxBatchQueryStatus::eSUCCESS && result.nbHits == 1)
{
PxRaycastHit& hit = result.hits[0];
mDistances[i] = hit.distance;
// ...
}
// ...
}
好了,到这里,PhysX SDK 3.2中的场景查询该如何使用,就介绍完了。最好的使用参考还是代码,大家可以多在PhysX SDK提供的Sample中做一些测试,更快的熟悉该如何使用这些查询功能。