697 lines
24 KiB
C++
697 lines
24 KiB
C++
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2025 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 "extensions/PxSceneQueryExt.h"
|
|
#include "geometry/PxGeometryHelpers.h"
|
|
#include "foundation/PxAllocatorCallback.h"
|
|
#include "CmUtils.h"
|
|
#include "foundation/PxAllocator.h"
|
|
|
|
using namespace physx;
|
|
|
|
bool PxSceneQueryExt::raycastAny( const PxScene& scene,
|
|
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryHit& hit, const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
|
{
|
|
PxSceneQueryFilterData fdAny = filterData;
|
|
fdAny.flags |= PxQueryFlag::eANY_HIT;
|
|
PxRaycastBuffer buf;
|
|
scene.raycast(origin, unitDir, distance, buf, PxHitFlag::eANY_HIT, fdAny, filterCall, cache);
|
|
hit = buf.block;
|
|
return buf.hasBlock;
|
|
}
|
|
|
|
bool PxSceneQueryExt::raycastSingle(const PxScene& scene,
|
|
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryFlags outputFlags, PxRaycastHit& hit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
|
{
|
|
PxRaycastBuffer buf;
|
|
PxQueryFilterData fd1 = filterData;
|
|
scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
|
|
hit = buf.block;
|
|
return buf.hasBlock;
|
|
}
|
|
|
|
PxI32 PxSceneQueryExt::raycastMultiple( const PxScene& scene,
|
|
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryFlags outputFlags,
|
|
PxRaycastHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
|
{
|
|
PxRaycastBuffer buf(hitBuffer, hitBufferSize);
|
|
PxQueryFilterData fd1 = filterData;
|
|
scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
|
|
blockingHit = buf.hasBlock;
|
|
if(blockingHit)
|
|
{
|
|
if(buf.nbTouches < hitBufferSize)
|
|
{
|
|
hitBuffer[buf.nbTouches] = buf.block;
|
|
return PxI32(buf.nbTouches+1);
|
|
}
|
|
else // overflow, drop the last touch
|
|
{
|
|
hitBuffer[hitBufferSize-1] = buf.block;
|
|
return -1;
|
|
}
|
|
} else
|
|
// no block
|
|
return PxI32(buf.nbTouches);
|
|
}
|
|
|
|
bool PxSceneQueryExt::sweepAny( const PxScene& scene,
|
|
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryFlags queryFlags,
|
|
PxSceneQueryHit& hit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall,
|
|
const PxSceneQueryCache* cache,
|
|
PxReal inflation)
|
|
{
|
|
PxSceneQueryFilterData fdAny = filterData;
|
|
fdAny.flags |= PxQueryFlag::eANY_HIT;
|
|
PxSweepBuffer buf;
|
|
scene.sweep(geometry, pose, unitDir, distance, buf, queryFlags|PxHitFlag::eANY_HIT, fdAny, filterCall, cache, inflation);
|
|
hit = buf.block;
|
|
return buf.hasBlock;
|
|
}
|
|
|
|
bool PxSceneQueryExt::sweepSingle( const PxScene& scene,
|
|
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryFlags outputFlags,
|
|
PxSweepHit& hit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall,
|
|
const PxSceneQueryCache* cache,
|
|
PxReal inflation)
|
|
{
|
|
PxSweepBuffer buf;
|
|
PxQueryFilterData fd1 = filterData;
|
|
scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
|
|
hit = buf.block;
|
|
return buf.hasBlock;
|
|
}
|
|
|
|
PxI32 PxSceneQueryExt::sweepMultiple( const PxScene& scene,
|
|
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
|
PxSceneQueryFlags outputFlags, PxSweepHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
|
|
PxReal inflation)
|
|
{
|
|
PxQueryFilterData fd1 = filterData;
|
|
PxSweepBuffer buf(hitBuffer, hitBufferSize);
|
|
scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
|
|
blockingHit = buf.hasBlock;
|
|
if(blockingHit)
|
|
{
|
|
if(buf.nbTouches < hitBufferSize)
|
|
{
|
|
hitBuffer[buf.nbTouches] = buf.block;
|
|
return PxI32(buf.nbTouches+1);
|
|
}
|
|
else // overflow, drop the last touch
|
|
{
|
|
hitBuffer[hitBufferSize-1] = buf.block;
|
|
return -1;
|
|
}
|
|
} else
|
|
// no block
|
|
return PxI32(buf.nbTouches);
|
|
}
|
|
|
|
PxI32 PxSceneQueryExt::overlapMultiple( const PxScene& scene,
|
|
const PxGeometry& geometry, const PxTransform& pose,
|
|
PxOverlapHit* hitBuffer, PxU32 hitBufferSize,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall)
|
|
{
|
|
PxQueryFilterData fd1 = filterData;
|
|
fd1.flags |= PxQueryFlag::eNO_BLOCK;
|
|
PxOverlapBuffer buf(hitBuffer, hitBufferSize);
|
|
scene.overlap(geometry, pose, buf, fd1, filterCall);
|
|
if(buf.hasBlock)
|
|
{
|
|
if(buf.nbTouches < hitBufferSize)
|
|
{
|
|
hitBuffer[buf.nbTouches] = buf.block;
|
|
return PxI32(buf.nbTouches+1);
|
|
}
|
|
else // overflow, drop the last touch
|
|
{
|
|
hitBuffer[hitBufferSize-1] = buf.block;
|
|
return -1;
|
|
}
|
|
} else
|
|
// no block
|
|
return PxI32(buf.nbTouches);
|
|
}
|
|
|
|
bool PxSceneQueryExt::overlapAny( const PxScene& scene,
|
|
const PxGeometry& geometry, const PxTransform& pose,
|
|
PxOverlapHit& hit,
|
|
const PxSceneQueryFilterData& filterData,
|
|
PxSceneQueryFilterCallback* filterCall)
|
|
{
|
|
PxSceneQueryFilterData fdAny = filterData;
|
|
fdAny.flags |= (PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK);
|
|
PxOverlapBuffer buf;
|
|
scene.overlap(geometry, pose, buf, fdAny, filterCall);
|
|
hit = buf.block;
|
|
return buf.hasBlock;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
struct Raycast
|
|
{
|
|
PxVec3 origin;
|
|
PxVec3 unitDir;
|
|
PxReal distance;
|
|
PxHitFlags hitFlags;
|
|
PxQueryFilterData filterData;
|
|
const PxQueryCache* cache;
|
|
};
|
|
struct Sweep
|
|
{
|
|
PxGeometryHolder geometry;
|
|
PxTransform pose;
|
|
PxVec3 unitDir;
|
|
PxReal distance;
|
|
PxHitFlags hitFlags;
|
|
PxQueryFilterData filterData;
|
|
const PxQueryCache* cache;
|
|
PxReal inflation;
|
|
};
|
|
struct Overlap
|
|
{
|
|
PxGeometryHolder geometry;
|
|
PxTransform pose;
|
|
PxQueryFilterData filterData;
|
|
const PxQueryCache* cache;
|
|
};
|
|
}
|
|
|
|
template<typename HitType>
|
|
struct NpOverflowBuffer : PxHitBuffer<HitType>
|
|
{
|
|
bool overflow;
|
|
bool processCalled;
|
|
PxU32 saveNbTouches;
|
|
NpOverflowBuffer(HitType* hits, PxU32 count) : PxHitBuffer<HitType>(hits, count), overflow(false), processCalled(false), saveNbTouches(0)
|
|
{
|
|
}
|
|
|
|
virtual PxAgain processTouches(const HitType* /*hits*/, PxU32 /*count*/)
|
|
{
|
|
if (processCalled)
|
|
return false;
|
|
saveNbTouches = this->nbTouches;
|
|
processCalled = true;
|
|
return true;
|
|
}
|
|
|
|
virtual void finalizeQuery()
|
|
{
|
|
if (processCalled)
|
|
{
|
|
overflow = (this->nbTouches > 0);
|
|
this->nbTouches = saveNbTouches;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
class ExtBatchQuery : public PxBatchQueryExt
|
|
{
|
|
PX_NOCOPY(ExtBatchQuery)
|
|
public:
|
|
|
|
ExtBatchQuery(
|
|
const PxScene& scene,
|
|
PxQueryFilterCallback* queryFilterCallback,
|
|
PxRaycastBuffer* raycastBuffers, Raycast* raycastQueries, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
|
PxSweepBuffer* sweepBuffers, Sweep* sweepQueries, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
|
PxOverlapBuffer* overlapBuffers, Overlap* overlapQueries, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches);
|
|
|
|
~ExtBatchQuery() {}
|
|
|
|
virtual void release();
|
|
|
|
virtual PxRaycastBuffer* raycast(
|
|
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, const PxU16 maxNbTouches,
|
|
PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT),
|
|
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
|
const PxQueryCache* cache = NULL);
|
|
|
|
virtual PxSweepBuffer* sweep(
|
|
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, const PxU16 maxNbTouches,
|
|
PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT),
|
|
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
|
const PxQueryCache* cache = NULL,
|
|
const PxReal inflation = 0.f);
|
|
|
|
virtual PxOverlapBuffer* overlap(
|
|
const PxGeometry& geometry, const PxTransform& pose, PxU16 maxNbTouches = 0,
|
|
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
|
const PxQueryCache* cache = NULL);
|
|
|
|
virtual void execute();
|
|
|
|
private:
|
|
|
|
template<typename HitType, typename QueryType> struct Query
|
|
{
|
|
PxHitBuffer<HitType>* mBuffers;
|
|
QueryType* mQueries;
|
|
PxU32 mMaxNbBuffers;
|
|
HitType* mTouches;
|
|
PxU32 mMaxNbTouches;
|
|
|
|
PxU32 mBufferTide;
|
|
|
|
Query()
|
|
: mBuffers(NULL),
|
|
mQueries(NULL),
|
|
mMaxNbBuffers(0),
|
|
mTouches(NULL),
|
|
mMaxNbTouches(0),
|
|
mBufferTide(0)
|
|
{
|
|
}
|
|
|
|
Query(PxHitBuffer<HitType>* buffers, QueryType* queries, const PxU32 maxNbBuffers, HitType* touches, const PxU32 maxNbTouches)
|
|
: mBuffers(buffers),
|
|
mQueries(queries),
|
|
mMaxNbBuffers(maxNbBuffers),
|
|
mTouches(touches),
|
|
mMaxNbTouches(maxNbTouches),
|
|
mBufferTide(0)
|
|
{
|
|
for (PxU32 i = 0; i < mMaxNbBuffers; i++)
|
|
{
|
|
mBuffers[i].hasBlock = false;
|
|
mBuffers[i].nbTouches = 0;
|
|
}
|
|
}
|
|
|
|
PxHitBuffer<HitType>* addQuery(const QueryType& query, const PxU32 maxNbTouches)
|
|
{
|
|
if ((mBufferTide + 1) > mMaxNbBuffers)
|
|
{
|
|
//Ran out of queries.
|
|
return NULL;
|
|
}
|
|
|
|
PxHitBuffer<HitType>* buffer = mBuffers + mBufferTide;
|
|
buffer->touches = NULL;
|
|
buffer->maxNbTouches = maxNbTouches;
|
|
buffer->hasBlock = false;
|
|
buffer->nbTouches = 0xffffffff;
|
|
|
|
mQueries[mBufferTide] = query;
|
|
|
|
mBufferTide++;
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static void performQuery(const PxScene& scene, const Raycast& query, NpOverflowBuffer<PxRaycastHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
|
{
|
|
scene.raycast(
|
|
query.origin, query.unitDir, query.distance,
|
|
hitBuffer,
|
|
query.hitFlags,
|
|
query.filterData, qfcb,
|
|
query.cache);
|
|
}
|
|
|
|
static void performQuery(const PxScene& scene, const Sweep& query, NpOverflowBuffer<PxSweepHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
|
{
|
|
scene.sweep(
|
|
query.geometry.any(), query.pose, query.unitDir, query.distance,
|
|
hitBuffer,
|
|
query.hitFlags,
|
|
query.filterData, qfcb,
|
|
query.cache,
|
|
query.inflation);
|
|
}
|
|
|
|
static void performQuery(const PxScene& scene, const Overlap& query, NpOverflowBuffer<PxOverlapHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
|
{
|
|
scene.overlap(
|
|
query.geometry.any(), query.pose,
|
|
hitBuffer,
|
|
query.filterData, qfcb,
|
|
query.cache);
|
|
}
|
|
|
|
void execute(const PxScene& scene, PxQueryFilterCallback* qfcb)
|
|
{
|
|
PxU32 touchesTide = 0;
|
|
for (PxU32 i = 0; i < mBufferTide; i++)
|
|
{
|
|
PX_ASSERT(0xffffffff == mBuffers[i].nbTouches);
|
|
PX_ASSERT(0xffffffff != mBuffers[i].maxNbTouches);
|
|
PX_ASSERT(!mBuffers[i].touches);
|
|
|
|
bool noTouchesRemaining = false;
|
|
if (mBuffers[i].maxNbTouches > 0)
|
|
{
|
|
if (touchesTide >= mMaxNbTouches)
|
|
{
|
|
//No resources left.
|
|
mBuffers[i].maxNbTouches = 0;
|
|
mBuffers[i].touches = NULL;
|
|
noTouchesRemaining = true;
|
|
}
|
|
else if ((touchesTide + mBuffers[i].maxNbTouches) > mMaxNbTouches)
|
|
{
|
|
//Some resources left but not enough to match requested number.
|
|
//This might be enough but it depends on the number of hits generated by the query.
|
|
mBuffers[i].maxNbTouches = mMaxNbTouches - touchesTide;
|
|
mBuffers[i].touches = mTouches + touchesTide;
|
|
}
|
|
else
|
|
{
|
|
//Enough resources left to match request.
|
|
mBuffers[i].touches = mTouches + touchesTide;
|
|
}
|
|
}
|
|
|
|
bool overflow = false;
|
|
{
|
|
PX_ALIGN(16, NpOverflowBuffer<HitType> overflowBuffer)(mBuffers[i].touches, mBuffers[i].maxNbTouches);
|
|
performQuery(scene, mQueries[i], overflowBuffer, qfcb);
|
|
overflow = overflowBuffer.overflow || noTouchesRemaining;
|
|
mBuffers[i].hasBlock = overflowBuffer.hasBlock;
|
|
mBuffers[i].block = overflowBuffer.block;
|
|
mBuffers[i].nbTouches = overflowBuffer.nbTouches;
|
|
}
|
|
|
|
if(overflow)
|
|
{
|
|
mBuffers[i].maxNbTouches = 0xffffffff;
|
|
}
|
|
touchesTide += mBuffers[i].nbTouches;
|
|
}
|
|
|
|
mBufferTide = 0;
|
|
}
|
|
};
|
|
|
|
const PxScene& mScene;
|
|
PxQueryFilterCallback* mQueryFilterCallback;
|
|
|
|
Query<PxRaycastHit, Raycast> mRaycasts;
|
|
Query<PxSweepHit, Sweep> mSweeps;
|
|
Query<PxOverlapHit, Overlap> mOverlaps;
|
|
};
|
|
|
|
template<typename HitType>
|
|
class ExtBatchQueryDesc
|
|
{
|
|
public:
|
|
ExtBatchQueryDesc(const PxU32 maxNbResults, const PxU32 maxNbTouches)
|
|
: mResults(NULL),
|
|
mMaxNbResults(maxNbResults),
|
|
mTouches(NULL),
|
|
mMaxNbTouches(maxNbTouches)
|
|
{
|
|
}
|
|
ExtBatchQueryDesc(PxHitBuffer<HitType>* results, const PxU32 maxNbResults, HitType* touches, PxU32 maxNbTouches)
|
|
: mResults(results),
|
|
mMaxNbResults(maxNbResults),
|
|
mTouches(touches),
|
|
mMaxNbTouches(maxNbTouches)
|
|
{
|
|
}
|
|
|
|
PX_FORCE_INLINE PxHitBuffer<HitType>* getResults() const { return mResults; }
|
|
PX_FORCE_INLINE PxU32 getNbResults() const { return mMaxNbResults; }
|
|
PX_FORCE_INLINE HitType* getTouches() const { return mTouches; }
|
|
PX_FORCE_INLINE PxU32 getNbTouches() const { return mMaxNbTouches; }
|
|
|
|
private:
|
|
PxHitBuffer<HitType>* mResults;
|
|
PxU32 mMaxNbResults;
|
|
HitType* mTouches;
|
|
PxU32 mMaxNbTouches;
|
|
};
|
|
|
|
template <typename HitType, typename QueryType>
|
|
PxU32 computeByteSize(const ExtBatchQueryDesc<HitType>& queryDesc)
|
|
{
|
|
PxU32 byteSize = 0;
|
|
if (queryDesc.getNbResults() > 0)
|
|
{
|
|
byteSize += sizeof(QueryType)*queryDesc.getNbResults();
|
|
if (!queryDesc.getResults())
|
|
{
|
|
byteSize += sizeof(PxHitBuffer<HitType>)*queryDesc.getNbResults() + sizeof(HitType)*queryDesc.getNbTouches();
|
|
}
|
|
}
|
|
return byteSize;
|
|
}
|
|
|
|
template <typename HitType, typename QueryType> PxU8* parseDesc
|
|
(PxU8* bufIn, const ExtBatchQueryDesc<HitType>& queryDesc,
|
|
PxHitBuffer<HitType>*& results,
|
|
QueryType*& queries,
|
|
PxU32& maxBufferSize,
|
|
HitType*& touches,
|
|
PxU32& maxNbTouches)
|
|
{
|
|
PxU8* bufOut = bufIn;
|
|
|
|
results = queryDesc.getResults();
|
|
queries = NULL;
|
|
maxBufferSize = queryDesc.getNbResults();
|
|
touches = queryDesc.getTouches();
|
|
maxNbTouches = queryDesc.getNbTouches();
|
|
|
|
if (maxBufferSize > 0)
|
|
{
|
|
queries = reinterpret_cast<QueryType*>(bufOut);
|
|
bufOut += sizeof(QueryType)*maxBufferSize;
|
|
|
|
if (!results)
|
|
{
|
|
results = reinterpret_cast<PxHitBuffer<HitType>*>(bufOut);
|
|
for (PxU32 i = 0; i < maxBufferSize; i++)
|
|
{
|
|
PX_PLACEMENT_NEW(results + i, PxHitBuffer<HitType>);
|
|
}
|
|
bufOut += sizeof(PxHitBuffer<HitType>)*maxBufferSize;
|
|
|
|
if (maxNbTouches > 0)
|
|
{
|
|
touches = reinterpret_cast<HitType*>(bufOut);
|
|
bufOut += sizeof(HitType)*maxNbTouches;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bufOut;
|
|
}
|
|
|
|
PxBatchQueryExt* create
|
|
(const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
|
const ExtBatchQueryDesc<PxRaycastHit>& raycastDesc, const ExtBatchQueryDesc<PxSweepHit>& sweepDesc, const ExtBatchQueryDesc<PxOverlapHit>& overlapDesc)
|
|
{
|
|
const PxU32 byteSize =
|
|
sizeof(ExtBatchQuery) +
|
|
computeByteSize<PxRaycastHit, Raycast>(raycastDesc) +
|
|
computeByteSize<PxSweepHit, Sweep>(sweepDesc) +
|
|
computeByteSize<PxOverlapHit, Overlap>(overlapDesc);
|
|
|
|
PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
|
|
|
|
PxU8* buf = reinterpret_cast<PxU8*>(allocator.allocate(byteSize, "NpBatchQueryExt", PX_FL));
|
|
PX_CHECK_AND_RETURN_NULL(buf, "PxCreateBatchQueryExt - alllocation failed");
|
|
ExtBatchQuery* bq = reinterpret_cast<ExtBatchQuery*>(buf);
|
|
buf += sizeof(ExtBatchQuery);
|
|
|
|
PxHitBuffer<PxRaycastHit>* raycastBuffers = NULL;
|
|
Raycast* raycastQueries = NULL;
|
|
PxU32 maxNbRaycasts = 0;
|
|
PxRaycastHit* raycastTouches = NULL;
|
|
PxU32 maxNbRaycastTouches = 0;
|
|
buf = parseDesc<PxRaycastHit, Raycast>(buf, raycastDesc, raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches);
|
|
|
|
PxHitBuffer<PxSweepHit>* sweepBuffers = NULL;
|
|
Sweep* sweepQueries = NULL;
|
|
PxU32 maxNbSweeps = 0;
|
|
PxSweepHit* sweepTouches = NULL;
|
|
PxU32 maxNbSweepTouches = 0;
|
|
buf = parseDesc<PxSweepHit, Sweep>(buf, sweepDesc, sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches);
|
|
|
|
PxHitBuffer<PxOverlapHit>* overlapBuffers = NULL;
|
|
Overlap* overlapQueries = NULL;
|
|
PxU32 maxNbOverlaps = 0;
|
|
PxOverlapHit* overlapTouches = NULL;
|
|
PxU32 maxNbOverlapTouches = 0;
|
|
buf = parseDesc<PxOverlapHit, Overlap>(buf, overlapDesc, overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
|
|
|
PX_ASSERT((reinterpret_cast<PxU8*>(bq) + byteSize) == buf);
|
|
|
|
PX_PLACEMENT_NEW(bq, ExtBatchQuery)(
|
|
scene, queryFilterCallback,
|
|
raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches,
|
|
sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches,
|
|
overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
|
|
|
return bq;
|
|
}
|
|
|
|
PxBatchQueryExt* physx::PxCreateBatchQueryExt(
|
|
const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
|
const PxU32 maxNbRaycasts, const PxU32 maxNbRaycastTouches,
|
|
const PxU32 maxNbSweeps, const PxU32 maxNbSweepTouches,
|
|
const PxU32 maxNbOverlaps, const PxU32 maxNbOverlapTouches)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbRaycastTouches) && (0 == maxNbRaycasts)),
|
|
"PxCreateBatchQueryExt - maxNbRaycastTouches is non-zero but maxNbRaycasts is zero");
|
|
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbSweepTouches) && (0 == maxNbSweeps)),
|
|
"PxCreateBatchQueryExt - maxNbSweepTouches is non-zero but maxNbSweeps is zero");
|
|
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbOverlapTouches) && (0 == maxNbOverlaps)),
|
|
"PxCreateBatchQueryExt - maxNbOverlaps is non-zero but maxNbOverlaps is zero");
|
|
|
|
return create(scene, queryFilterCallback,
|
|
ExtBatchQueryDesc<PxRaycastHit>(maxNbRaycasts, maxNbRaycastTouches),
|
|
ExtBatchQueryDesc<PxSweepHit>(maxNbSweeps, maxNbSweepTouches),
|
|
ExtBatchQueryDesc<PxOverlapHit>(maxNbOverlaps, maxNbOverlapTouches));
|
|
}
|
|
|
|
PxBatchQueryExt* physx::PxCreateBatchQueryExt(
|
|
const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
|
PxRaycastBuffer* raycastBuffers, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
|
PxSweepBuffer* sweepBuffers, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
|
PxOverlapBuffer* overlapBuffers, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(!(!raycastTouches && (maxNbRaycastTouches != 0)),
|
|
"PxCreateBatchQueryExt - maxNbRaycastTouches > 0 but raycastTouches is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!raycastBuffers && (maxNbRaycasts != 0)),
|
|
"PxCreateBatchQueryExt - maxNbRaycasts > 0 but raycastBuffers is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!raycastBuffers && raycastTouches),
|
|
"PxCreateBatchQueryExt - raycastBuffers is NULL but raycastTouches is non-NULL");
|
|
|
|
PX_CHECK_AND_RETURN_NULL(!(!sweepTouches && (maxNbSweepTouches != 0)),
|
|
"PxCreateBatchQueryExt - maxNbSweepTouches > 0 but sweepTouches is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!sweepBuffers && (maxNbSweeps != 0)),
|
|
"PxCreateBatchQueryExt - maxNbSweeps > 0 but sweepBuffers is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!sweepBuffers && sweepTouches),
|
|
"PxCreateBatchQueryExt - sweepBuffers is NULL but sweepTouches is non-NULL");
|
|
|
|
PX_CHECK_AND_RETURN_NULL(!(!overlapTouches && (maxNbOverlapTouches != 0)),
|
|
"PxCreateBatchQueryExt - maxNbOverlapTouches > 0 but overlapTouches is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!overlapBuffers && (maxNbOverlaps != 0)),
|
|
"PxCreateBatchQueryExt - maxNbOverlaps > 0 but overlapBuffers is NULL");
|
|
PX_CHECK_AND_RETURN_NULL(!(!overlapBuffers && overlapTouches),
|
|
"PxCreateBatchQueryExt - overlapBuffers is NULL but overlapTouches is non-NULL");
|
|
|
|
return create(scene, queryFilterCallback,
|
|
ExtBatchQueryDesc<PxRaycastHit>(raycastBuffers, maxNbRaycasts, raycastTouches, maxNbRaycastTouches),
|
|
ExtBatchQueryDesc<PxSweepHit>(sweepBuffers, maxNbSweeps, sweepTouches, maxNbSweepTouches),
|
|
ExtBatchQueryDesc<PxOverlapHit>(overlapBuffers, maxNbOverlaps, overlapTouches, maxNbOverlapTouches));
|
|
}
|
|
|
|
|
|
ExtBatchQuery::ExtBatchQuery
|
|
(const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
|
PxRaycastBuffer* raycastBuffers, Raycast* raycastQueries, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
|
PxSweepBuffer* sweepBuffers, Sweep* sweepQueries, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
|
PxOverlapBuffer* overlapBuffers, Overlap* overlapQueries, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches)
|
|
: mScene(scene),
|
|
mQueryFilterCallback(queryFilterCallback)
|
|
{
|
|
typedef Query<PxRaycastHit, Raycast> QueryRaycast;
|
|
typedef Query<PxSweepHit, Sweep> QuerySweep;
|
|
typedef Query<PxOverlapHit, Overlap> QueryOverlap;
|
|
PX_PLACEMENT_NEW(&mRaycasts, QueryRaycast)(raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches);
|
|
PX_PLACEMENT_NEW(&mSweeps, QuerySweep)(sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches);
|
|
PX_PLACEMENT_NEW(&mOverlaps, QueryOverlap)(overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
|
}
|
|
|
|
void ExtBatchQuery::release()
|
|
{
|
|
PxGetAllocatorCallback()->deallocate(this);
|
|
}
|
|
|
|
PxRaycastBuffer* ExtBatchQuery::raycast
|
|
(const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
const PxU16 maxNbTouches,
|
|
PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData,
|
|
const PxQueryCache* cache)
|
|
{
|
|
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
|
const Raycast raycast = { origin, unitDir, distance, hitFlags, qfd, cache };
|
|
PxRaycastBuffer* buffer = mRaycasts.addQuery(raycast, maxNbTouches);
|
|
PX_CHECK_MSG(buffer, "PxBatchQueryExt::raycast - number of raycast() calls exceeds maxNbRaycasts. query discarded");
|
|
return buffer;
|
|
}
|
|
|
|
PxSweepBuffer* ExtBatchQuery::sweep
|
|
(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
|
const PxU16 maxNbTouches,
|
|
PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData,
|
|
const PxQueryCache* cache,
|
|
const PxReal inflation)
|
|
{
|
|
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
|
const Sweep sweep = { geometry, pose, unitDir, distance, hitFlags, qfd, cache, inflation};
|
|
PxSweepBuffer* buffer = mSweeps.addQuery(sweep, maxNbTouches);
|
|
PX_CHECK_MSG(buffer, "PxBatchQueryExt::sweep - number of sweep() calls exceeds maxNbSweeps. query discarded");
|
|
return buffer;
|
|
}
|
|
|
|
PxOverlapBuffer* ExtBatchQuery::overlap
|
|
(const PxGeometry& geometry, const PxTransform& pose, PxU16 maxNbTouches,
|
|
const PxQueryFilterData& filterData,
|
|
const PxQueryCache* cache)
|
|
{
|
|
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
|
const Overlap overlap = { geometry, pose, qfd, cache};
|
|
PxOverlapBuffer* buffer = mOverlaps.addQuery(overlap, maxNbTouches);
|
|
PX_CHECK_MSG(buffer, "PxBatchQueryExt::overlap - number of overlap() calls exceeds maxNbOverlaps. query discarded");
|
|
return buffer;
|
|
}
|
|
|
|
void ExtBatchQuery::execute()
|
|
{
|
|
mRaycasts.execute(mScene, mQueryFilterCallback);
|
|
mSweeps.execute(mScene, mQueryFilterCallback);
|
|
mOverlaps.execute(mScene, mQueryFilterCallback);
|
|
}
|