470 lines
20 KiB
C++
470 lines
20 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/PxSceneQuerySystemExt.h"
|
|
#include "extensions/PxShapeExt.h"
|
|
#include "foundation/PxAlloca.h"
|
|
#include "foundation/PxHashMap.h"
|
|
#include "foundation/PxUserAllocated.h"
|
|
#include "geometry/PxBVH.h"
|
|
#include "GuActorShapeMap.h"
|
|
#include "SqQuery.h"
|
|
#include "SqFactory.h"
|
|
#include "PxRigidActor.h"
|
|
#include "PxPruningStructure.h"
|
|
#include "PxSceneDesc.h" // PT: for PxSceneLimits TODO: remove
|
|
|
|
// PT: this file re-implements a scene-queries system for PxScene inside PxExtensions. All SQ-related calls from the PxScene API
|
|
// will be re-routed to this class. This version re-uses the same internal code as PhysX (most notably from SqQuery.h) so there is
|
|
// little differences between the internal PhysX version and this one except minor implementation details like what we store in the
|
|
// PrunerPayload. The whole API is available, it uses the same number of "pruners" for the queries, etc. This is a good working
|
|
// starting point for users who want to start tinkering with the system without starting from scratch.
|
|
|
|
using namespace physx;
|
|
using namespace Sq;
|
|
using namespace Gu;
|
|
|
|
#define EXT_PRUNER_EPSILON 0.005f
|
|
|
|
// PT: in this external implementation we'll use Px pointers instead of Np pointers in the payload.
|
|
static PX_FORCE_INLINE void setPayload(PrunerPayload& pp, const PxShape* shape, const PxRigidActor* actor)
|
|
{
|
|
pp.data[0] = size_t(shape);
|
|
pp.data[1] = size_t(actor);
|
|
}
|
|
|
|
static PX_FORCE_INLINE PxShape* getShapeFromPayload(const PrunerPayload& payload)
|
|
{
|
|
return reinterpret_cast<PxShape*>(payload.data[0]);
|
|
}
|
|
|
|
static PX_FORCE_INLINE PxRigidActor* getActorFromPayload(const PrunerPayload& payload)
|
|
{
|
|
return reinterpret_cast<PxRigidActor*>(payload.data[1]);
|
|
}
|
|
|
|
static PX_FORCE_INLINE bool isDynamicActor(const PxRigidActor& actor)
|
|
{
|
|
const PxType actorType = actor.getConcreteType();
|
|
return actorType != PxConcreteType::eRIGID_STATIC;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
static PX_FORCE_INLINE ActorShapeData createActorShapeData(PrunerData data, PrunerCompoundId id) { return (ActorShapeData(id) << 32) | ActorShapeData(data); }
|
|
static PX_FORCE_INLINE PrunerData getPrunerData(ActorShapeData data) { return PrunerData(data); }
|
|
static PX_FORCE_INLINE PrunerCompoundId getCompoundID(ActorShapeData data) { return PrunerCompoundId(data >> 32); }
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace
|
|
{
|
|
class ExtSqAdapter : public QueryAdapter
|
|
{
|
|
public:
|
|
ExtSqAdapter() {}
|
|
virtual ~ExtSqAdapter() {}
|
|
|
|
// Adapter
|
|
virtual const PxGeometry& getGeometry(const PrunerPayload& payload) const;
|
|
//~Adapter
|
|
|
|
// QueryAdapter
|
|
virtual PrunerHandle findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const;
|
|
virtual void getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const;
|
|
virtual void getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const;
|
|
//~QueryAdapter
|
|
|
|
ActorShapeMap mDatabase;
|
|
};
|
|
}
|
|
|
|
const PxGeometry& ExtSqAdapter::getGeometry(const PrunerPayload& payload) const
|
|
{
|
|
PxShape* shape = getShapeFromPayload(payload);
|
|
return shape->getGeometry();
|
|
}
|
|
|
|
PrunerHandle ExtSqAdapter::findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const
|
|
{
|
|
const PxU32 actorIndex = cache.actor->getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
const ActorShapeData actorShapeData = mDatabase.find(actorIndex, cache.actor, cache.shape);
|
|
|
|
const PrunerData prunerData = getPrunerData(actorShapeData);
|
|
compoundId = getCompoundID(actorShapeData);
|
|
|
|
prunerIndex = getPrunerIndex(prunerData);
|
|
return getPrunerHandle(prunerData);
|
|
}
|
|
|
|
void ExtSqAdapter::getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const
|
|
{
|
|
PxShape* shape = getShapeFromPayload(payload);
|
|
filterData = shape->getQueryFilterData();
|
|
}
|
|
|
|
void ExtSqAdapter::getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const
|
|
{
|
|
actorShape.actor = getActorFromPayload(payload);
|
|
actorShape.shape = getShapeFromPayload(payload);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace
|
|
{
|
|
class ExternalPxSQ : public PxSceneQuerySystem, public PxUserAllocated
|
|
{
|
|
public:
|
|
ExternalPxSQ(PVDCapture* pvd, PxU64 contextID, Pruner* staticPruner, Pruner* dynamicPruner,
|
|
PxU32 dynamicTreeRebuildRateHint, PxSceneQueryUpdateMode::Enum mode, const PxSceneLimits& limits) :
|
|
mQueries (pvd, contextID, staticPruner, dynamicPruner, dynamicTreeRebuildRateHint, EXT_PRUNER_EPSILON, limits, mExtAdapter),
|
|
mUpdateMode (mode),
|
|
mRefCount (1)
|
|
{}
|
|
virtual ~ExternalPxSQ() {}
|
|
|
|
virtual void release();
|
|
virtual void acquireReference();
|
|
virtual void preallocate(PxU32 prunerIndex, PxU32 nbShapes) { SQ().preallocate(prunerIndex, nbShapes); }
|
|
virtual void addSQShape( const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds,
|
|
const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure);
|
|
virtual void removeSQShape(const PxRigidActor& actor, const PxShape& shape);
|
|
virtual void updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform);
|
|
virtual PxSQCompoundHandle addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& pxbvh, const PxTransform* transforms);
|
|
virtual void removeSQCompound(PxSQCompoundHandle compoundHandle);
|
|
virtual void updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform);
|
|
virtual void flushUpdates() { SQ().flushUpdates(); }
|
|
virtual void flushMemory() { SQ().flushMemory(); }
|
|
virtual void visualize(PxU32 prunerIndex, PxRenderOutput& out) const { SQ().visualize(prunerIndex, out); }
|
|
virtual void shiftOrigin(const PxVec3& shift) { SQ().shiftOrigin(shift); }
|
|
virtual PxSQBuildStepHandle prepareSceneQueryBuildStep(PxU32 prunerIndex);
|
|
virtual void sceneQueryBuildStep(PxSQBuildStepHandle handle);
|
|
virtual void finalizeUpdates();
|
|
virtual void setDynamicTreeRebuildRateHint(PxU32 dynTreeRebuildRateHint) { SQ().setDynamicTreeRebuildRateHint(dynTreeRebuildRateHint); }
|
|
virtual PxU32 getDynamicTreeRebuildRateHint() const { return SQ().getDynamicTreeRebuildRateHint(); }
|
|
virtual void forceRebuildDynamicTree(PxU32 prunerIndex) { SQ().forceRebuildDynamicTree(prunerIndex); }
|
|
virtual PxSceneQueryUpdateMode::Enum getUpdateMode() const { return mUpdateMode; }
|
|
virtual void setUpdateMode(PxSceneQueryUpdateMode::Enum mode) { mUpdateMode = mode; }
|
|
virtual PxU32 getStaticTimestamp() const { return SQ().getStaticTimestamp(); }
|
|
virtual void merge(const PxPruningStructure& pxps);
|
|
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
|
virtual bool sweep( const PxGeometry& geometry, const PxTransform& pose,
|
|
const PxVec3& unitDir, const PxReal distance,
|
|
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const;
|
|
virtual bool overlap(const PxGeometry& geometry, const PxTransform& transform,
|
|
PxOverlapCallback& hitCall,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
|
virtual PxSQPrunerHandle getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const;
|
|
virtual void sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
|
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices);
|
|
|
|
PX_FORCE_INLINE PrunerManager& SQ() { return mQueries.mSQManager; }
|
|
PX_FORCE_INLINE const PrunerManager& SQ() const { return mQueries.mSQManager; }
|
|
|
|
ExtSqAdapter mExtAdapter;
|
|
SceneQueries mQueries;
|
|
PxSceneQueryUpdateMode::Enum mUpdateMode;
|
|
PxU32 mRefCount;
|
|
};
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void addExternalSQ(PxSceneQuerySystem* added);
|
|
void removeExternalSQ(PxSceneQuerySystem* removed);
|
|
|
|
void ExternalPxSQ::release()
|
|
{
|
|
mRefCount--;
|
|
if(!mRefCount)
|
|
{
|
|
removeExternalSQ(this);
|
|
PX_DELETE_THIS;
|
|
}
|
|
}
|
|
|
|
void ExternalPxSQ::acquireReference()
|
|
{
|
|
mRefCount++;
|
|
}
|
|
|
|
void ExternalPxSQ::addSQShape(const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds, const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure)
|
|
{
|
|
PrunerPayload payload;
|
|
setPayload(payload, &shape, &actor);
|
|
|
|
const PrunerCompoundId cid = compoundHandle ? PrunerCompoundId(*compoundHandle) : INVALID_COMPOUND_ID;
|
|
const PrunerData prunerData = SQ().addPrunerShape(payload, isDynamicActor(actor), cid, bounds, transform, hasPruningStructure);
|
|
|
|
const PxU32 actorIndex = actor.getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
mExtAdapter.mDatabase.add(actorIndex, &actor, &shape, createActorShapeData(prunerData, cid));
|
|
}
|
|
|
|
namespace
|
|
{
|
|
struct DatabaseCleaner : PrunerPayloadRemovalCallback
|
|
{
|
|
DatabaseCleaner(ExtSqAdapter& adapter) : mAdapter(adapter){}
|
|
|
|
virtual void invoke(PxU32 nbRemoved, const PrunerPayload* removed) PX_OVERRIDE PX_FINAL
|
|
{
|
|
PxU32 actorIndex = 0xffffffff;
|
|
const PxRigidActor* cachedActor = NULL;
|
|
|
|
while(nbRemoved--)
|
|
{
|
|
const PrunerPayload& payload = *removed++;
|
|
|
|
const PxRigidActor* actor = getActorFromPayload(payload);
|
|
|
|
if(actor!=cachedActor)
|
|
{
|
|
actorIndex = actor->getInternalActorIndex();
|
|
cachedActor = actor;
|
|
}
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
bool status = mAdapter.mDatabase.remove(actorIndex, actor, getShapeFromPayload(payload), NULL);
|
|
PX_ASSERT(status);
|
|
PX_UNUSED(status);
|
|
}
|
|
}
|
|
ExtSqAdapter& mAdapter;
|
|
|
|
PX_NOCOPY(DatabaseCleaner)
|
|
};
|
|
}
|
|
|
|
void ExternalPxSQ::removeSQShape(const PxRigidActor& actor, const PxShape& shape)
|
|
{
|
|
const PxU32 actorIndex = actor.getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
ActorShapeData actorShapeData;
|
|
mExtAdapter.mDatabase.remove(actorIndex, &actor, &shape, &actorShapeData);
|
|
|
|
const PrunerData data = getPrunerData(actorShapeData);
|
|
const PrunerCompoundId compoundId = getCompoundID(actorShapeData);
|
|
|
|
SQ().removePrunerShape(compoundId, data, NULL);
|
|
}
|
|
|
|
void ExternalPxSQ::updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform)
|
|
{
|
|
const PxU32 actorIndex = actor.getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
|
|
|
const PrunerData shapeHandle = getPrunerData(actorShapeData);
|
|
const PrunerCompoundId cid = getCompoundID(actorShapeData);
|
|
|
|
SQ().markForUpdate(cid, shapeHandle, transform);
|
|
}
|
|
|
|
PxSQCompoundHandle ExternalPxSQ::addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& bvh, const PxTransform* transforms)
|
|
{
|
|
const PxU32 numSqShapes = bvh.getNbBounds();
|
|
|
|
PX_ALLOCA(payloads, PrunerPayload, numSqShapes);
|
|
for(PxU32 i=0; i<numSqShapes; i++)
|
|
setPayload(payloads[i], shapes[i], &actor);
|
|
|
|
const PxU32 actorIndex = actor.getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
PX_ALLOCA(shapeHandles, PrunerData, numSqShapes);
|
|
SQ().addCompoundShape(bvh, actorIndex, actor.getGlobalPose(), shapeHandles, payloads, transforms, isDynamicActor(actor));
|
|
|
|
for(PxU32 i=0; i<numSqShapes; i++)
|
|
{
|
|
// PT: TODO: actorIndex is now redundant!
|
|
mExtAdapter.mDatabase.add(actorIndex, &actor, shapes[i], createActorShapeData(shapeHandles[i], actorIndex));
|
|
}
|
|
|
|
return PxSQCompoundHandle(actorIndex);
|
|
}
|
|
|
|
void ExternalPxSQ::removeSQCompound(PxSQCompoundHandle compoundHandle)
|
|
{
|
|
DatabaseCleaner cleaner(mExtAdapter);
|
|
SQ().removeCompoundActor(PrunerCompoundId(compoundHandle), &cleaner);
|
|
}
|
|
|
|
void ExternalPxSQ::updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform)
|
|
{
|
|
SQ().updateCompoundActor(PrunerCompoundId(compoundHandle), compoundTransform);
|
|
}
|
|
|
|
PxSQBuildStepHandle ExternalPxSQ::prepareSceneQueryBuildStep(PxU32 prunerIndex)
|
|
{
|
|
return SQ().prepareSceneQueriesUpdate(PruningIndex::Enum(prunerIndex));
|
|
}
|
|
|
|
void ExternalPxSQ::sceneQueryBuildStep(PxSQBuildStepHandle handle)
|
|
{
|
|
SQ().sceneQueryBuildStep(handle);
|
|
}
|
|
|
|
void ExternalPxSQ::finalizeUpdates()
|
|
{
|
|
switch(mUpdateMode)
|
|
{
|
|
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_ENABLED: SQ().afterSync(true, true); break;
|
|
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED: SQ().afterSync(true, false); break;
|
|
case PxSceneQueryUpdateMode::eBUILD_DISABLED_COMMIT_DISABLED: SQ().afterSync(false, false); break;
|
|
}
|
|
}
|
|
|
|
void ExternalPxSQ::merge(const PxPruningStructure& pxps)
|
|
{
|
|
Pruner* staticPruner = SQ().getPruner(PruningIndex::eSTATIC);
|
|
if(staticPruner)
|
|
staticPruner->merge(pxps.getStaticMergeData());
|
|
|
|
Pruner* dynamicPruner = SQ().getPruner(PruningIndex::eDYNAMIC);
|
|
if(dynamicPruner)
|
|
dynamicPruner->merge(pxps.getDynamicMergeData());
|
|
}
|
|
|
|
bool ExternalPxSQ::raycast( const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
|
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
|
{
|
|
return mQueries._raycast(origin, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, flags);
|
|
}
|
|
|
|
bool ExternalPxSQ::sweep( const PxGeometry& geometry, const PxTransform& pose,
|
|
const PxVec3& unitDir, const PxReal distance,
|
|
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const
|
|
{
|
|
return mQueries._sweep(geometry, pose, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, inflation, flags);
|
|
}
|
|
|
|
bool ExternalPxSQ::overlap( const PxGeometry& geometry, const PxTransform& transform,
|
|
PxOverlapCallback& hitCall,
|
|
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
|
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
|
{
|
|
return mQueries._overlap( geometry, transform, hitCall, filterData, filterCall, cache, flags);
|
|
}
|
|
|
|
PxSQPrunerHandle ExternalPxSQ::getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const
|
|
{
|
|
const PxU32 actorIndex = actor.getInternalActorIndex();
|
|
PX_ASSERT(actorIndex!=0xffffffff);
|
|
|
|
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
|
|
|
const PrunerData prunerData = getPrunerData(actorShapeData);
|
|
|
|
prunerIndex = getPrunerIndex(prunerData);
|
|
|
|
return PxSQPrunerHandle(getPrunerHandle(prunerData));
|
|
}
|
|
|
|
void ExternalPxSQ::sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
|
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices)
|
|
{
|
|
PX_ASSERT(prunerIndex==PruningIndex::eDYNAMIC);
|
|
if(prunerIndex==PruningIndex::eDYNAMIC)
|
|
SQ().sync(handles, indices, bounds, transforms, count, ignoredIndices);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
static CompanionPrunerType getCompanionType(PxDynamicTreeSecondaryPruner::Enum type)
|
|
{
|
|
switch(type)
|
|
{
|
|
case PxDynamicTreeSecondaryPruner::eNONE: return COMPANION_PRUNER_NONE;
|
|
case PxDynamicTreeSecondaryPruner::eBUCKET: return COMPANION_PRUNER_BUCKET;
|
|
case PxDynamicTreeSecondaryPruner::eINCREMENTAL: return COMPANION_PRUNER_INCREMENTAL;
|
|
case PxDynamicTreeSecondaryPruner::eBVH: return COMPANION_PRUNER_AABB_TREE;
|
|
case PxDynamicTreeSecondaryPruner::eLAST: return COMPANION_PRUNER_NONE;
|
|
}
|
|
return COMPANION_PRUNER_NONE;
|
|
}
|
|
|
|
static BVHBuildStrategy getBuildStrategy(PxBVHBuildStrategy::Enum bs)
|
|
{
|
|
switch(bs)
|
|
{
|
|
case PxBVHBuildStrategy::eFAST: return BVH_SPLATTER_POINTS;
|
|
case PxBVHBuildStrategy::eDEFAULT: return BVH_SPLATTER_POINTS_SPLIT_GEOM_CENTER;
|
|
case PxBVHBuildStrategy::eSAH: return BVH_SAH;
|
|
case PxBVHBuildStrategy::eLAST: return BVH_SPLATTER_POINTS;
|
|
}
|
|
return BVH_SPLATTER_POINTS;
|
|
}
|
|
|
|
static Pruner* create(PxPruningStructureType::Enum type, PxU64 contextID, PxDynamicTreeSecondaryPruner::Enum secondaryType, PxBVHBuildStrategy::Enum buildStrategy, PxU32 nbObjectsPerNode)
|
|
{
|
|
// if(0)
|
|
// return createIncrementalPruner(contextID);
|
|
|
|
const CompanionPrunerType cpType = getCompanionType(secondaryType);
|
|
const BVHBuildStrategy bs = getBuildStrategy(buildStrategy);
|
|
|
|
Pruner* pruner = NULL;
|
|
switch(type)
|
|
{
|
|
case PxPruningStructureType::eNONE: { pruner = createBucketPruner(contextID); break; }
|
|
case PxPruningStructureType::eDYNAMIC_AABB_TREE: { pruner = createAABBPruner(contextID, true, cpType, bs, nbObjectsPerNode); break; }
|
|
case PxPruningStructureType::eSTATIC_AABB_TREE: { pruner = createAABBPruner(contextID, false, cpType, bs, nbObjectsPerNode); break; }
|
|
case PxPruningStructureType::eLAST: break;
|
|
}
|
|
return pruner;
|
|
}
|
|
|
|
PxSceneQuerySystem* physx::PxCreateExternalSceneQuerySystem(const PxSceneQueryDesc& desc, PxU64 contextID)
|
|
{
|
|
PVDCapture* pvd = NULL;
|
|
Pruner* staticPruner = create(desc.staticStructure, contextID, desc.dynamicTreeSecondaryPruner, desc.staticBVHBuildStrategy, desc.staticNbObjectsPerNode);
|
|
Pruner* dynamicPruner = create(desc.dynamicStructure, contextID, desc.dynamicTreeSecondaryPruner, desc.dynamicBVHBuildStrategy, desc.dynamicNbObjectsPerNode);
|
|
|
|
ExternalPxSQ* pxsq = PX_NEW(ExternalPxSQ)(pvd, contextID, staticPruner, dynamicPruner, desc.dynamicTreeRebuildRateHint, desc.sceneQueryUpdateMode, PxSceneLimits());
|
|
|
|
addExternalSQ(pxsq);
|
|
|
|
return pxsq;
|
|
}
|