diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp')
| -rw-r--r-- | PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp new file mode 100644 index 00000000..f428e706 --- /dev/null +++ b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp @@ -0,0 +1,602 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "NpBatchQuery.h" +#include "NpReadCheck.h" +#include "NpActor.h" +#include "NpShapeManager.h" +#include "PsAtomic.h" +#include "PsFoundation.h" +#include "PsUtilities.h" +#include "NpScene.h" + +using namespace physx; +using namespace Sq; +using namespace Cm; + +#if !PX_P64_FAMILY +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxRaycastHit)& 0x0f)); +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxSweepHit)& 0x0f)); +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxOverlapHit)& 0x0f)); +#endif + +#define CHECK_RUNNING(QueryMessage) \ + if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, -1, 0) == 1)\ + {\ + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, QueryMessage); return;\ + } + +NpBatchQuery::NpBatchQuery(NpScene& owner, const PxBatchQueryDesc& d) + : mNpScene(&owner), mNbRaycasts(0), mNbOverlaps(0), mNbSweeps(0), mBatchQueryIsRunning(0), mDesc(d), mPrevOffset(PxU32(eTERMINAL)) +{ + mHasMtdSweep = false; +} + +NpBatchQuery::~NpBatchQuery() +{ +} + +void NpBatchQuery::setUserMemory(const PxBatchQueryMemory& userMem) +{ + if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, 0, 0) != 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::setUserMemory: This batch is still executing, skipping setUserMemory"); + return; + } + + PxBatchQueryDesc& desc = getDesc(); + + desc.queryMemory = userMem; +} + +const PxBatchQueryMemory& NpBatchQuery::getUserMemory() +{ + return getDesc().queryMemory; +} + +// ROS abbreviates Raycast/Overlap/Sweep +struct QTypeROS { enum Enum { eRAYCAST = 0, eOVERLAP = 1, eSWEEP = 2 }; }; // AP: perhaps can be shared with some other code + +namespace physx +{ +struct BatchStreamHeader +{ + BatchStreamHeader( + PxHitFlags aHitFlags, const PxQueryCache* aCache, const PxQueryFilterData& aFd, + void* aUserData, PxU16 aMaxTouchHits, QTypeROS::Enum aHitTypeId) : + hitFlags(aHitFlags), fd(aFd), userData(aUserData), cache(aCache), + maxTouchHits(aMaxTouchHits), hitTypeId(char(aHitTypeId)) + { + nextQueryOffset = PxU32(NpBatchQuery::eTERMINAL); + } + + BatchStreamHeader() {} + + // TODO: possibly maintain 3 separate offset lists in the same array for raycasts/overlaps/sweeps + // offset of a 4-byte ptr to offset in the previously stored batch query in the stream, this is not a ptr because of reallocs + PxU32 nextQueryOffset; + PxHitFlags hitFlags; + PxQueryFilterData fd; + void* userData; + const PxQueryCache* cache; + PxU16 maxTouchHits; + char hitTypeId; // Sq::QTypeROS +}; +} // namespace physx + +static void writeGeom(BatchQueryStream& stream, const PxGeometry& geom) +{ + PxGeometryType::Enum geomType = geom.getType(); + stream.write<PxU32>(PxU32(geomType)); + switch (geomType) + { + case PxGeometryType::eCAPSULE: + stream.write<PxCapsuleGeometry>(static_cast<const PxCapsuleGeometry&>(geom)); + break; + case PxGeometryType::eSPHERE: + stream.write<PxSphereGeometry>(static_cast<const PxSphereGeometry&>(geom)); + break; + case PxGeometryType::eCONVEXMESH: + stream.write<PxConvexMeshGeometry>(static_cast<const PxConvexMeshGeometry&>(geom)); + break; + case PxGeometryType::eBOX: + stream.write<PxBoxGeometry>(static_cast<const PxBoxGeometry&>(geom)); + break; + case PxGeometryType::ePLANE: + case PxGeometryType::eTRIANGLEMESH: + case PxGeometryType::eHEIGHTFIELD: + case PxGeometryType::eGEOMETRY_COUNT: + case PxGeometryType::eINVALID: + PX_ALWAYS_ASSERT_MESSAGE("Unsupported geometry type in writeGeom"); + } +} + +static PxGeometry* readGeom(BatchQueryStreamReader& reader) +{ + PxU32 geomType = *reader.read<PxU32>(); + PxGeometry* anyGeom = NULL; + switch (geomType) + { + case PxGeometryType::eCAPSULE: + anyGeom = reader.read<PxCapsuleGeometry>(); + break; + case PxGeometryType::eSPHERE: + anyGeom = reader.read<PxSphereGeometry>(); + break; + case PxGeometryType::eCONVEXMESH: + anyGeom = reader.read<PxConvexMeshGeometry>(); + break; + case PxGeometryType::eBOX: + anyGeom = reader.read<PxBoxGeometry>(); + break; + default: + PX_ALWAYS_ASSERT_MESSAGE("Unsupported geometry type in readGeom"); + } + + return anyGeom; +} + +static void writeQueryInput(BatchQueryStream& stream, const MultiQueryInput& input) +{ + stream.write<MultiQueryInput>(input); + if (input.rayOrigin) + stream.write<PxVec3>(input.rayOrigin); + if (input.unitDir) + stream.write<PxVec3>(input.unitDir); + if (input.pose) + stream.write<PxTransform>(input.pose); + if (input.geometry) + writeGeom(stream, *input.geometry); +} + +static MultiQueryInput* readQueryInput(BatchQueryStreamReader& stream) +{ + MultiQueryInput* input = stream.read<MultiQueryInput>(); + if (input->rayOrigin) + input->rayOrigin = stream.read<PxVec3>(); + if (input->unitDir) + input->unitDir = stream.read<PxVec3>(); + if (input->pose) + input->pose = stream.read<PxTransform>(); + if (input->geometry) + input->geometry = readGeom(stream); + + return input; +} + +template<typename ResultType, typename HitType> +void writeStatus(ResultType* aRes, const PxHitBuffer<HitType>& hits, void* userData, bool overflow) +{ + ResultType* res = aRes; + res->userData = userData; + res->block = hits.block; + res->hasBlock = hits.hasBlock; + res->nbTouches = hits.nbTouches; + res->queryStatus = PxU8(overflow ? PxBatchQueryStatus::eOVERFLOW : PxBatchQueryStatus::eSUCCESS); + res->touches = (overflow && res->nbTouches == 0) ? NULL : hits.touches; +} + +void NpBatchQuery::resetResultBuffers() +{ + for (PxU32 i = 0; i<mNbRaycasts; i++) + { + mDesc.queryMemory.userRaycastResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING; + mDesc.queryMemory.userRaycastResultBuffer[i].hasBlock = false; + mDesc.queryMemory.userRaycastResultBuffer[i].nbTouches = 0; + mDesc.queryMemory.userRaycastResultBuffer[i].touches = NULL; + mDesc.queryMemory.userRaycastResultBuffer[i].userData = NULL; + } + for (PxU32 i = 0; i<mNbOverlaps; i++) + { + mDesc.queryMemory.userOverlapResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING; + mDesc.queryMemory.userOverlapResultBuffer[i].hasBlock = false; + mDesc.queryMemory.userOverlapResultBuffer[i].nbTouches = 0; + mDesc.queryMemory.userOverlapResultBuffer[i].touches = NULL; + mDesc.queryMemory.userOverlapResultBuffer[i].userData = NULL; + } + for (PxU32 i = 0; i<mNbSweeps; i++) + { + mDesc.queryMemory.userSweepResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING; + mDesc.queryMemory.userSweepResultBuffer[i].hasBlock = false; + mDesc.queryMemory.userSweepResultBuffer[i].nbTouches = 0; + mDesc.queryMemory.userSweepResultBuffer[i].touches = NULL; + mDesc.queryMemory.userSweepResultBuffer[i].userData = NULL; + } +} + +void NpBatchQuery::finalizeExecute() +{ + mPrevOffset = PxU32(eTERMINAL); // reset the first BatchStreamHeader offset + mStream.rewind(); // clear out the executed queries - rewind the data stream so that the query object can be reused + mNbRaycasts = mNbOverlaps = mNbSweeps = 0; // also reset the counts so the query object can be reused + mHasMtdSweep = false; // reset the mtd flag + + Ps::atomicExchange(&mBatchQueryIsRunning, 0); +} + +// fixed memory buffer with extra single hit for overflow detection +template<typename HitType> +struct PxOverflowBuffer : PxHitBuffer<HitType> +{ + bool overflow; + PxU32 saveNbTouches; + HitType extraHit; + HitType* saveTouches; + bool processCalled; + PxOverflowBuffer(HitType* hits, PxU32 count) : PxHitBuffer<HitType>(hits, count), overflow(false), processCalled(false) + { + } + + virtual PxAgain processTouches(const HitType* /*hits*/, PxU32 /*count*/) + { + if (processCalled) + return false; + saveTouches = this->touches; + saveNbTouches = this->nbTouches; + processCalled = true; + this->touches = &extraHit; + this->maxNbTouches = 1; + return true; + } + + virtual void finalizeQuery() + { + if (processCalled) + { + overflow = (this->nbTouches > 0); + this->nbTouches = saveNbTouches; + this->touches = saveTouches; + } + } +}; + +void NpBatchQuery::execute() +{ + NP_READ_CHECK(mNpScene); + + if(mNbRaycasts) + { + PX_CHECK_AND_RETURN(mDesc.queryMemory.userRaycastResultBuffer!=NULL, "PxBatchQuery execute: userRaycastResultBuffer is NULL"); + PX_CHECK_AND_RETURN(mDesc.queryMemory.raycastTouchBufferSize > 0 ? + (mDesc.queryMemory.userRaycastTouchBuffer != NULL) : true, "PxBatchQuery execute: userRaycastTouchBuffer is NULL"); + } + if(mNbOverlaps) + { + PX_CHECK_AND_RETURN(mDesc.queryMemory.userOverlapResultBuffer!=NULL, "PxBatchQuery execute: userOverlapResultBuffer is NULL"); + PX_CHECK_AND_RETURN(mDesc.queryMemory.overlapTouchBufferSize > 0 ? + (mDesc.queryMemory.userOverlapTouchBuffer != NULL) : true, "PxBatchQuery execute: userOverlapTouchBuffer is NULL"); + } + if(mNbSweeps) + { + PX_CHECK_AND_RETURN(mDesc.queryMemory.userSweepResultBuffer!=NULL, "PxBatchQuery execute: userSweepResultBuffer is NULL"); + PX_CHECK_AND_RETURN(mDesc.queryMemory.sweepTouchBufferSize > 0 ? + (mDesc.queryMemory.userSweepTouchBuffer != NULL) : true, "PxBatchQuery execute: userSweepTouchBuffer is NULL"); + } + + PX_SIMD_GUARD; + + PX_PROFILE_ZONE("BatchedSceneQuery.execute", mNpScene->getContextId()); + PxI32 ret = Ps::atomicCompareExchange(&mBatchQueryIsRunning, 1, 0); + if(ret == 1) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::execute: This batch is already executing"); + return; + } + else if(ret == -1) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::execute: Another thread is still adding queries to this batch"); + return; + } + + resetResultBuffers(); + + // If PVD is connected and IS_PVD_SQ_ENABLED, record the offsets for queries in pvd buffers and run the queries on PPU + bool isSqCollectorLocked = false; + PX_UNUSED(isSqCollectorLocked); + +#if PX_SUPPORT_PVD + PxU32 pvdRayQstartIdx = 0; + PxU32 pvdOverlapQstartIdx = 0; + PxU32 pvdSweepQstartIdx = 0; + + Vd::ScbScenePvdClient& pvdClient = mNpScene->mScene.getScenePvdClient(); + const bool needUpdatePvd = pvdClient.checkPvdDebugFlag() && (pvdClient.getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES); + + if(needUpdatePvd) + { + mNpScene->getBatchedSqCollector().getLock().lock(); + isSqCollectorLocked = true; + + pvdRayQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedRaycastQueries.size(); + pvdOverlapQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedOverlapQueries.size(); + pvdSweepQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedSweepQueries.size(); + } +#endif + + PxClientID clientId = mDesc.ownerClient; + + // setup local pointers to user provided output buffers + PxRaycastHit* raycastHits = mDesc.queryMemory.userRaycastTouchBuffer; PX_UNUSED(raycastHits); + PxRaycastQueryResult* raycastResults = mDesc.queryMemory.userRaycastResultBuffer; PX_UNUSED(raycastResults); + PxU32 raycastHitsSize = mDesc.queryMemory.raycastTouchBufferSize; PX_UNUSED(raycastHitsSize); + + PxOverlapHit* overlapHits = mDesc.queryMemory.userOverlapTouchBuffer; PX_UNUSED(overlapHits); + PxOverlapQueryResult* overlapResults = mDesc.queryMemory.userOverlapResultBuffer; PX_UNUSED(overlapResults); + PxU32 overlapHitsSize = mDesc.queryMemory.overlapTouchBufferSize; PX_UNUSED(overlapHitsSize); + + PxSweepHit* sweepHits = mDesc.queryMemory.userSweepTouchBuffer; PX_UNUSED(sweepHits); + PxSweepQueryResult* sweepResults = mDesc.queryMemory.userSweepResultBuffer; PX_UNUSED(sweepResults); + PxU32 sweepHitsSize = mDesc.queryMemory.sweepTouchBufferSize; PX_UNUSED(sweepHitsSize); + + BatchQueryFilterData bfd(mDesc.filterShaderData, mDesc.filterShaderDataSize, mDesc.preFilterShader, mDesc.postFilterShader); + + // data declarations for double buffering the input stream + PxU32 curQueryOffset = 0; // first query starts at 0 + if (mPrevOffset == eTERMINAL) // except if zero queries were queued + { + finalizeExecute(); + return; + } + + PxU32 hitsSpaceLeft; PX_UNUSED(hitsSpaceLeft); + + // ====================== parse and execute the batch query memory stream ====================== + PxU32 queryCount = 0; + do { + // parse a query from the input stream, create a stream reader at current double buffer + BatchQueryStreamReader reader(mStream.begin()+curQueryOffset); + BatchStreamHeader& h = *reader.read<BatchStreamHeader>(); + if (h.fd.clientId == 0) + h.fd.clientId = clientId; // override a zero clientId with PxBatchQueryDesc.ownerClient + + curQueryOffset = h.nextQueryOffset; + Ps::prefetchLine(mStream.begin() + curQueryOffset); + + MultiQueryInput& input = *readQueryInput(reader); + + // ====================== switch over query type - QTypeROS::eRAYCAST, eOVERLAP, eSWEEP ===================== + switch (h.hitTypeId) + { + // =============== Current query is a raycast ===================== + case QTypeROS::eRAYCAST: + { + PxU32 nbRaycastHits = PxU32(raycastHits - mDesc.queryMemory.userRaycastTouchBuffer); + PX_ASSERT(nbRaycastHits <= raycastHitsSize); + hitsSpaceLeft = raycastHitsSize - nbRaycastHits; + PxOverflowBuffer<PxRaycastHit> hits(raycastHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft)); + mNpScene->NpScene::multiQuery<PxRaycastHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd); + hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0 + writeStatus<PxRaycastQueryResult, PxRaycastHit>(raycastResults++, hits, h.userData, hits.overflow); + raycastHits += hits.nbTouches; + } break; + + // ================ Current query is an overlap ==================== + case QTypeROS::eOVERLAP: + { + PxU32 nbOverlapHits = PxU32(overlapHits - mDesc.queryMemory.userOverlapTouchBuffer); + PX_ASSERT(nbOverlapHits <= overlapHitsSize); + hitsSpaceLeft = overlapHitsSize - nbOverlapHits; + PxOverflowBuffer<PxOverlapHit> hits(overlapHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft)); + mNpScene->NpScene::multiQuery<PxOverlapHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd); + hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0 + writeStatus<PxOverlapQueryResult, PxOverlapHit>(overlapResults++, hits, h.userData, hits.overflow); + overlapHits += hits.nbTouches; + } break; + + // ================== Current query is a sweep ========================= + case QTypeROS::eSWEEP: + { + + PxU32 nbSweepHits = PxU32(sweepHits - mDesc.queryMemory.userSweepTouchBuffer); + PX_ASSERT(nbSweepHits <= sweepHitsSize); + hitsSpaceLeft = sweepHitsSize - nbSweepHits; + PxOverflowBuffer<PxSweepHit> hits(sweepHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft)); + mNpScene->NpScene::multiQuery<PxSweepHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd); + hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0 + writeStatus<PxSweepQueryResult, PxSweepHit>(sweepResults++, hits, h.userData, hits.overflow); + sweepHits += hits.nbTouches; + } break; + default: + PX_ALWAYS_ASSERT_MESSAGE("Unexpected batch query type (raycast/overlap/sweep)."); + } + + if (h.nextQueryOffset == eTERMINAL) // end of stream + // AP: previously also had a break on hitCount==-1 which is aborted due to out of space + // abort stream parsing if we ran into an aborted query (hitCount==-1).. but it was easier to just continue + // the perf implications for aborted queries are not a significant consideration and this allows to avoid + // writing special case code for filling the query buffers after aborted query + break; + #undef MULTIQ + queryCount++; + } while (queryCount < 1000000); + +#if PX_SUPPORT_PVD + if( isSqCollectorLocked && needUpdatePvd) + { + mNpScene->getBatchedSqCollector().collectAllBatchedHits( mDesc.queryMemory.userRaycastResultBuffer, mNbRaycasts, pvdRayQstartIdx, + mDesc.queryMemory.userOverlapResultBuffer, mNbOverlaps, pvdOverlapQstartIdx, + mDesc.queryMemory.userSweepResultBuffer, mNbSweeps, pvdSweepQstartIdx); + } + + // Maybe connection is disconnected after the lock + if( isSqCollectorLocked ) + { + mNpScene->getBatchedSqCollector().getLock().unlock(); + isSqCollectorLocked = false; + } +#endif + + finalizeExecute(); +} + +/////////////////////////////////////////////////////////////////////////////// +void NpBatchQuery::writeBatchHeader(const BatchStreamHeader& h) +{ + PxU32 streamPos = PxU32(mStream.getPos()); // save the stream pos before we write the header + mStream.write<BatchStreamHeader>(h); + // link into a list as offset + PxU32* prevPtr = (mPrevOffset == eTERMINAL) ? &mPrevOffset : reinterpret_cast<PxU32*>(mStream.begin()+mPrevOffset); + PxU32 headerPtr = streamPos+PX_OFFSET_OF(BatchStreamHeader, nextQueryOffset); + *prevPtr = headerPtr; + mPrevOffset = headerPtr; +} + +/////////////////////////////////////////////////////////////////////////////// +void NpBatchQuery::raycast( + const PxVec3& origin, const PxVec3& unitDir, PxReal distance, PxU16 maxTouchHits, + PxHitFlags hitFlags, const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache) +{ + PX_CHECK_AND_RETURN(distance>0, "PxBatchQuery::raycast: The maximum distance must be greater than zero!"); + PX_CHECK_AND_RETURN(unitDir.isNormalized(), "PxBatchQuery::raycast: Direction must be normalized"); + PX_CHECK_AND_RETURN(origin.isFinite(), "PxBatchQuery::raycast: origin is not valid"); + if (mNbRaycasts >= mDesc.queryMemory.getMaxRaycastsPerExecute()) + { + PX_CHECK_AND_RETURN(mNbRaycasts < mDesc.queryMemory.getMaxRaycastsPerExecute(), + "PxBatchQuery: number of raycast() calls exceeds PxBatchQueryMemory::raycastResultBufferSize, query discarded"); + return; + } + CHECK_RUNNING("PxBatchQuery::raycast: This batch is still executing, skipping query."); + mNbRaycasts++; + + writeBatchHeader(BatchStreamHeader(hitFlags, cache, fd, userData, maxTouchHits, QTypeROS::eRAYCAST)); + writeQueryInput(mStream, MultiQueryInput(origin, unitDir, distance)); + + Ps::atomicExchange(&mBatchQueryIsRunning, 0); +} + +/////////////////////////////////////////////////////////////////////////////// +void NpBatchQuery::overlap( + const PxGeometry& geometry, const PxTransform& pose, PxU16 maxTouchHits, + const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache) +{ + PX_CHECK_AND_RETURN(pose.isValid(), "NpBatchQuery::overlapMultiple pose is not valid."); + if (mNbOverlaps >= mDesc.queryMemory.getMaxOverlapsPerExecute()) + { + PX_CHECK_AND_RETURN(mNbOverlaps < mDesc.queryMemory.getMaxOverlapsPerExecute(), + "PxBatchQuery: number of overlap() calls exceeds PxBatchQueryMemory::overlapResultBufferSize, query discarded"); + return; + } + CHECK_RUNNING("PxBatchQuery::overlap: This batch is still executing, skipping query.") + mNbOverlaps++; + + writeBatchHeader(BatchStreamHeader(PxHitFlags(), cache, fd, userData, maxTouchHits, QTypeROS::eOVERLAP)); + writeQueryInput(mStream, MultiQueryInput(&geometry, &pose)); + + Ps::atomicExchange(&mBatchQueryIsRunning, 0); +} + +void NpBatchQuery::sweep( + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, PxU16 maxTouchHits, + PxHitFlags hitFlags, const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache, const PxReal inflation) +{ + PX_CHECK_AND_RETURN(pose.isValid(), "Batch sweep input check: pose is not valid."); + PX_CHECK_AND_RETURN(unitDir.isFinite(), "Batch sweep input check: unitDir is not valid."); + PX_CHECK_AND_RETURN(unitDir.isNormalized(), "Batch sweep input check: direction must be normalized"); + PX_CHECK_AND_RETURN(distance >= 0.0f, "Batch sweep input check: distance cannot be negative"); + PX_CHECK_AND_RETURN(distance != 0.0f || !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP), + "Batch sweep input check: zero-length sweep only valid without the PxHitFlag::eASSUME_NO_INITIAL_OVERLAP flag"); + + if (mNbSweeps >= mDesc.queryMemory.getMaxSweepsPerExecute()) + { + PX_CHECK_AND_RETURN(mNbSweeps < mDesc.queryMemory.getMaxSweepsPerExecute(), + "PxBatchQuery: number of sweep() calls exceeds PxBatchQueryMemory::sweepResultBufferSize, query discarded"); + return; + } + + + CHECK_RUNNING("PxBatchQuery::sweep: This batch is still executing, skipping query.") + mNbSweeps++; + + writeBatchHeader(BatchStreamHeader(hitFlags, cache, fd, userData, maxTouchHits, QTypeROS::eSWEEP)); + + //set the MTD flag + mHasMtdSweep |= !!(hitFlags & PxHitFlag::eMTD); + + if((hitFlags & PxHitFlag::ePRECISE_SWEEP) && (hitFlags & PxHitFlag::eMTD)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support MTD. Perform MTD with default sweep"); + hitFlags &= ~PxHitFlag::ePRECISE_SWEEP; + } + + if((hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP) && (hitFlags & PxHitFlag::eMTD)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " eMTD cannot be used in conjunction with eASSUME_NO_INITIAL_OVERLAP. eASSUME_NO_INITIAL_OVERLAP will be ignored"); + hitFlags &= ~PxHitFlag::eASSUME_NO_INITIAL_OVERLAP; + } + + PxReal realInflation = inflation; + if((hitFlags & PxHitFlag::ePRECISE_SWEEP)&& inflation > 0.f) + { + realInflation = 0.f; + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support inflation, inflation will be overwritten to be zero"); + } + + writeQueryInput(mStream, MultiQueryInput(&geometry, &pose, unitDir, distance, realInflation)); + + Ps::atomicExchange(&mBatchQueryIsRunning, 0); +} + +void NpBatchQuery::release() +{ + if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, 0, 0) != 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::release: This batch is still executing, skipping release"); + return; + } + + mNpScene->releaseBatchQuery(this); +} + +PxBatchQueryPreFilterShader NpBatchQuery::getPreFilterShader() const +{ + return mDesc.preFilterShader; +} + +PxBatchQueryPostFilterShader NpBatchQuery::getPostFilterShader() const +{ + return mDesc.postFilterShader; +} + +const void* NpBatchQuery::getFilterShaderData() const +{ + return mDesc.filterShaderData; +} + +PxU32 NpBatchQuery::getFilterShaderDataSize() const +{ + return mDesc.filterShaderDataSize; +} + +PxClientID NpBatchQuery::getOwnerClient() const +{ + return mDesc.ownerClient; +} + + |