Projekt_Grafika/dependencies/physx-4.1/source/physx/src/NpScene.h

481 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-2019 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PX_PHYSICS_NP_SCENE
#define PX_PHYSICS_NP_SCENE
#include "PsUserAllocated.h"
#include "PsSync.h"
#include "PsArray.h"
#include "PsThread.h"
#include "PsHashSet.h"
#include "PxPhysXConfig.h"
#if PX_SUPPORT_GPU_PHYSX
#include "device/PhysXIndicator.h"
#endif
#include "NpSceneQueries.h"
#include "NpSceneAccessor.h"
namespace physx
{
class PhysicsThread;
class PxBatchQueryDesc;
class NpMaterial;
class NpScene;
class NpArticulation;
namespace Sc
{
class Joint;
class ConstraintBreakEvent;
}
namespace Sq
{
class SceneQueryManager;
}
class NpObjectFactory;
class NpRigidStatic;
class NpRigidDynamic;
class NpConstraint;
class NpArticulationLink;
class NpShapeManager;
class NpBatchQuery;
class PxBatchQuery;
class NpContactCallbackTask : public physx::PxLightCpuTask
{
NpScene* mScene;
const PxContactPairHeader* mContactPairHeaders;
uint32_t mNbContactPairHeaders;
public:
void setData(NpScene* scene, const PxContactPairHeader* contactPairHeaders, const uint32_t nbContactPairHeaders);
virtual void run();
virtual const char* getName() const
{
return "NpContactCallbackTask";
}
};
class NpScene : public NpSceneQueries, public Ps::UserAllocated
{
//virtual interfaces:
PX_NOCOPY(NpScene)
public:
virtual void release();
virtual void setFlag(PxSceneFlag::Enum flag, bool value);
virtual PxSceneFlags getFlags() const;
// implement PxScene:
virtual void setGravity(const PxVec3&);
virtual PxVec3 getGravity() const;
virtual void setBounceThresholdVelocity(const PxReal t);
virtual PxReal getBounceThresholdVelocity() const;
virtual PxReal getFrictionOffsetThreshold() const;
virtual void setLimits(const PxSceneLimits& limits);
virtual PxSceneLimits getLimits() const;
virtual void addActor(PxActor& actor, const PxBVHStructure* bvhStructure);
virtual void removeActor(PxActor& actor, bool wakeOnLostTouch);
virtual PxU32 getNbConstraints() const;
virtual PxU32 getConstraints(PxConstraint** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
virtual void addArticulation(PxArticulationBase&);
virtual void removeArticulation(PxArticulationBase&, bool wakeOnLostTouch);
virtual PxU32 getNbArticulations() const;
virtual PxU32 getArticulations(PxArticulationBase** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
// Aggregates
virtual void addAggregate(PxAggregate&);
virtual void removeAggregate(PxAggregate&, bool wakeOnLostTouch);
virtual PxU32 getNbAggregates() const;
virtual PxU32 getAggregates(PxAggregate** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
virtual void addCollection(const PxCollection& collection);
// Groups
virtual void setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance);
virtual PxDominanceGroupPair getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const;
// Actors
virtual PxU32 getNbActors(PxActorTypeFlags types) const;
virtual PxU32 getActors(PxActorTypeFlags types, PxActor** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
virtual PxActor** getActiveActors(PxU32& nbActorsOut);
// Run
virtual void getSimulationStatistics(PxSimulationStatistics& s) const;
// Multiclient
virtual PxClientID createClient();
// FrictionModel
virtual void setFrictionType(PxFrictionType::Enum frictionType);
virtual PxFrictionType::Enum getFrictionType() const;
// Callbacks
virtual void setSimulationEventCallback(PxSimulationEventCallback* callback);
virtual PxSimulationEventCallback* getSimulationEventCallback() const;
virtual void setContactModifyCallback(PxContactModifyCallback* callback);
virtual PxContactModifyCallback* getContactModifyCallback() const;
virtual void setCCDContactModifyCallback(PxCCDContactModifyCallback* callback);
virtual PxCCDContactModifyCallback* getCCDContactModifyCallback() const;
virtual void setBroadPhaseCallback(PxBroadPhaseCallback* callback);
virtual PxBroadPhaseCallback* getBroadPhaseCallback() const;
//CCD passes
virtual void setCCDMaxPasses(PxU32 ccdMaxPasses);
virtual PxU32 getCCDMaxPasses() const;
// Collision filtering
virtual void setFilterShaderData(const void* data, PxU32 dataSize);
virtual const void* getFilterShaderData() const;
virtual PxU32 getFilterShaderDataSize() const;
virtual PxSimulationFilterShader getFilterShader() const;
virtual PxSimulationFilterCallback* getFilterCallback() const;
virtual void resetFiltering(PxActor& actor);
virtual void resetFiltering(PxRigidActor& actor, PxShape*const* shapes, PxU32 shapeCount);
virtual PxPairFilteringMode::Enum getKinematicKinematicFilteringMode() const;
virtual PxPairFilteringMode::Enum getStaticKinematicFilteringMode() const;
// Get Physics SDK
virtual PxPhysics& getPhysics();
// new API methods
virtual void simulate(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation);
virtual void advance(physx::PxBaseTask* completionTask);
virtual void collide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation = true);
virtual bool checkResults(bool block);
virtual bool checkCollision(bool block);
virtual bool fetchCollision(bool block);
virtual bool fetchResults(bool block, PxU32* errorState);
virtual bool fetchResultsStart(const PxContactPairHeader*& contactPairs, PxU32& nbContactPairs, bool block = false);
virtual void processCallbacks(physx::PxBaseTask* continuation);
virtual void fetchResultsFinish(PxU32* errorState = 0);
virtual void flush(bool sendPendingReports) { flushSimulation(sendPendingReports); }
virtual void flushSimulation(bool sendPendingReports);
virtual void flushQueryUpdates();
virtual const PxRenderBuffer& getRenderBuffer();
virtual PxBatchQuery* createBatchQuery(const PxBatchQueryDesc& desc);
void releaseBatchQuery(PxBatchQuery* bq);
virtual void setDynamicTreeRebuildRateHint(PxU32 dynamicTreeRebuildRateHint);
virtual PxU32 getDynamicTreeRebuildRateHint() const;
virtual void forceDynamicTreeRebuild(bool rebuildStaticStructure, bool rebuildDynamicStructure);
virtual void sceneQueriesUpdate(physx::PxBaseTask* completionTask, bool controlSimulation);
virtual bool checkQueries(bool block);
virtual bool fetchQueries(bool block);
virtual void setSceneQueryUpdateMode(PxSceneQueryUpdateMode::Enum updateMode);
virtual PxSceneQueryUpdateMode::Enum getSceneQueryUpdateMode() const;
virtual void setSolverBatchSize(PxU32 solverBatchSize);
virtual PxU32 getSolverBatchSize(void) const;
virtual void setSolverArticulationBatchSize(PxU32 solverBatchSize);
virtual PxU32 getSolverArticulationBatchSize(void) const;
virtual bool setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value);
virtual PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const;
virtual void setVisualizationCullingBox(const PxBounds3& box);
virtual PxBounds3 getVisualizationCullingBox() const;
virtual PxTaskManager* getTaskManager() { return mTaskManager; }
void checkBeginWrite() const {}
virtual PxCudaContextManager* getCudaContextManager() { return mCudaContextManager; }
virtual void setNbContactDataBlocks(PxU32 numBlocks);
virtual PxU32 getNbContactDataBlocksUsed() const;
virtual PxU32 getMaxNbContactDataBlocksUsed() const;
virtual PxU32 getContactReportStreamBufferSize() const;
virtual PxU32 getTimestamp() const;
virtual PxU32 getSceneQueryStaticTimestamp() const;
virtual PxCpuDispatcher* getCpuDispatcher() const;
virtual PxCudaContextManager* getCudaContextManager() const;
virtual PxPruningStructureType::Enum getStaticStructure() const;
virtual PxPruningStructureType::Enum getDynamicStructure() const;
virtual PxBroadPhaseType::Enum getBroadPhaseType() const;
virtual bool getBroadPhaseCaps(PxBroadPhaseCaps& caps) const;
virtual PxU32 getNbBroadPhaseRegions() const;
virtual PxU32 getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
virtual PxU32 addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion);
virtual bool removeBroadPhaseRegion(PxU32 handle);
virtual void addActors(PxActor*const* actors, PxU32 nbActors);
virtual void addActors(const PxPruningStructure& prunerStructure);
virtual void removeActors(PxActor*const* actors, PxU32 nbActors, bool wakeOnLostTouch);
virtual void lockRead(const char* file=NULL, PxU32 line=0);
virtual void unlockRead();
virtual void lockWrite(const char* file=NULL, PxU32 line=0);
virtual void unlockWrite();
virtual PxReal getWakeCounterResetValue() const;
virtual void shiftOrigin(const PxVec3& shift);
virtual PxPvdSceneClient* getScenePvdClient();
//Implementations for NpSceneAccessor interface!
virtual PxsSimulationController* getSimulationController();
virtual void setActiveActors(PxActor** actors, PxU32 nbActors);
virtual PxActor** getFrozenActors(PxU32& nbActorsOut);
virtual void setFrozenActorFlag(const bool buildFrozenActors);
virtual void forceSceneQueryRebuild();
virtual void frameEnd();
//internal public methods:
public:
NpScene(const PxSceneDesc& desc);
~NpScene();
PX_FORCE_INLINE PxTaskManager* getTaskManager() const { return mTaskManager; }
PX_FORCE_INLINE Sc::SimulationStage::Enum getSimulationStage() const { return mScene.getSimulationStage(); }
PX_FORCE_INLINE void setSimulationStage(Sc::SimulationStage::Enum stage) { mScene.setSimulationStage(stage); }
void addActorInternal(PxActor& actor, const PxBVHStructure* bvhStructure);
void removeActorInternal(PxActor& actor, bool wakeOnLostTouch, bool removeFromAggregate);
void addActorsInternal(PxActor*const* PX_RESTRICT actors, PxU32 nbActors, const Sq::PruningStructure* ps = NULL);
void addArticulationInternal(PxArticulationBase&);
void removeArticulationInternal(PxArticulationBase&, bool wakeOnLostTouch, bool removeFromAggregate);
// materials
void addMaterial(const NpMaterial& mat);
void updateMaterial(const NpMaterial& mat);
void removeMaterial(const NpMaterial& mat);
void executeScene(PxBaseTask* continuation);
void executeCollide(PxBaseTask* continuation);
void executeAdvance(PxBaseTask* continuation);
void constraintBreakEventNotify(PxConstraint *const *constraints, PxU32 count);
bool loadFromDesc(const PxSceneDesc&);
void removeFromRigidActorList(const PxU32&);
PX_FORCE_INLINE void removeFromArticulationList(PxArticulationBase&);
PX_FORCE_INLINE void removeFromAggregateList(PxAggregate&);
PX_FORCE_INLINE void addToConstraintList(PxConstraint&);
PX_FORCE_INLINE void removeFromConstraintList(PxConstraint&);
void addArticulationLink(NpArticulationLink& link);
void addArticulationLinkBody(NpArticulationLink& link);
void addArticulationLinkConstraint(NpArticulationLink& link);
void removeArticulationLink(NpArticulationLink& link, bool wakeOnLostTouch);
struct StartWriteResult
{
enum Enum { eOK, eNO_LOCK, eIN_FETCHRESULTS, eRACE_DETECTED };
};
StartWriteResult::Enum startWrite(bool allowReentry);
void stopWrite(bool allowReentry);
bool startRead() const;
void stopRead() const;
PxU32 getReadWriteErrorCount() const { return PxU32(mConcurrentErrorCount); }
#if PX_CHECKED
void checkPositionSanity(const PxRigidActor& a, const PxTransform& pose, const char* fnName) const;
#endif
#if PX_SUPPORT_GPU_PHYSX
void updatePhysXIndicator();
#else
PX_FORCE_INLINE void updatePhysXIndicator() {}
#endif
PX_FORCE_INLINE PxReal getWakeCounterResetValueInteral() const { return mScene.getWakeCounterResetValue(); }
private:
bool checkResultsInternal(bool block);
bool checkCollisionInternal(bool block);
bool checkSceneQueriesInternal(bool block);
void simulateOrCollide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation, const char* invalidCallMsg, Sc::SimulationStage::Enum simStage);
void addRigidStatic(NpRigidStatic& , const Gu::BVHStructure* bvhStructure, bool hasPrunerStructure = false);
void removeRigidStatic(NpRigidStatic&, bool wakeOnLostTouch, bool removeFromAggregate);
void addRigidDynamic(NpRigidDynamic& , const Gu::BVHStructure* bvhStructure, bool hasPrunerStructure = false);
void removeRigidDynamic(NpRigidDynamic&, bool wakeOnLostTouch, bool removeFromAggregate);
bool addRigidActorsInternal(PxU32 nbActors, PxActor** PX_RESTRICT actors);
void visualize();
void updateDirtyShaders();
void fireOutOfBoundsCallbacks();
void fetchResultsPreContactCallbacks();
void fetchResultsPostContactCallbacks();
void updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Actor& actor, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure);
PX_FORCE_INLINE void updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Body& body, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure);
Cm::RenderBuffer mRenderBuffer;
Ps::CoalescedHashSet<PxConstraint*> mConstraints;
Ps::Array<PxRigidActor*> mRigidActors; // no hash set used because it would be quite a bit slower when adding a large number of actors
Ps::CoalescedHashSet<PxArticulationBase*> mArticulations;
Ps::CoalescedHashSet<PxAggregate*> mAggregates;
Ps::Array<NpBatchQuery*> mBatchQueries;
PxBounds3 mSanityBounds;
#if PX_SUPPORT_GPU_PHYSX
PhysXIndicator mPhysXIndicator;
#endif
Ps::Sync mPhysicsDone; // physics thread signals this when update ready
Ps::Sync mCollisionDone; // physics thread signals this when all collisions ready
Ps::Sync mSceneQueriesDone; // physics thread signals this when all scene queries update ready
//legacy timing settings:
PxReal mElapsedTime; //needed to transfer the elapsed time param from the user to the sim thread.
PxU32 mNbClients; // Tracks reserved clients for multiclient support.
Ps::Array<PxU32> mClientBehaviorFlags;// Tracks behavior bits for clients.
struct SceneCompletion : public Cm::Task
{
SceneCompletion(PxU64 contextId, Ps::Sync& sync) : Cm::Task(contextId), mSync(sync){}
virtual void runInternal() {}
//ML: As soon as mSync.set is called, and the scene is shutting down,
//the scene may be deleted. That means this running task may also be deleted.
//As such, we call mSync.set() inside release() to avoid a crash because the v-table on this
//task might be deleted between the call to runInternal() and release() in the worker thread.
virtual void release()
{
//We cache the continuation pointer because this class may be deleted
//as soon as mSync.set() is called if the application releases the scene.
PxBaseTask* c = mCont;
//once mSync.set(), fetchResults() will be allowed to run.
mSync.set();
//Call the continuation task that we cached above. If we use mCont or
//any other member variable of this class, there is a small chance
//that the variables might have become corrupted if the class
//was deleted.
if(c) c->removeReference();
}
virtual const char* getName() const { return "NpScene.completion"; }
// //This method just is called in the split sim approach as a way to set continuation after the task has been initialized
void setDependent(PxBaseTask* task){PX_ASSERT(mCont == NULL); mCont = task; if(task)task->addReference();}
Ps::Sync& mSync;
private:
SceneCompletion& operator=(const SceneCompletion&);
};
typedef Cm::DelegateTask<NpScene, &NpScene::executeScene> SceneExecution;
typedef Cm::DelegateTask<NpScene, &NpScene::executeCollide> SceneCollide;
typedef Cm::DelegateTask<NpScene, &NpScene::executeAdvance> SceneAdvance;
PxTaskManager* mTaskManager;
PxCudaContextManager* mCudaContextManager;
SceneCompletion mSceneCompletion;
SceneCompletion mCollisionCompletion;
SceneCompletion mSceneQueriesCompletion;
SceneExecution mSceneExecution;
SceneCollide mSceneCollide;
SceneAdvance mSceneAdvance;
bool mControllingSimulation;
PxU32 mSimThreadStackSize;
volatile PxI32 mConcurrentWriteCount;
mutable volatile PxI32 mConcurrentReadCount;
mutable volatile PxI32 mConcurrentErrorCount;
// TLS slot index, keeps track of re-entry depth for this thread
PxU32 mThreadReadWriteDepth;
Ps::Thread::Id mCurrentWriter;
Ps::ReadWriteLock mRWLock;
bool mSceneQueriesUpdateRunning;
bool mHasSimulatedOnce;
bool mBetweenFetchResults;
bool mBuildFrozenActors;
};
PX_FORCE_INLINE void NpScene::addToConstraintList(PxConstraint& constraint)
{
mConstraints.insert(&constraint);
}
PX_FORCE_INLINE void NpScene::removeFromConstraintList(PxConstraint& constraint)
{
const bool exists = mConstraints.erase(&constraint);
PX_ASSERT(exists);
PX_UNUSED(exists);
}
PX_FORCE_INLINE void NpScene::removeFromArticulationList(PxArticulationBase& articulation)
{
const bool exists = mArticulations.erase(&articulation);
PX_ASSERT(exists);
PX_UNUSED(exists);
}
PX_FORCE_INLINE void NpScene::removeFromAggregateList(PxAggregate& aggregate)
{
const bool exists = mAggregates.erase(&aggregate);
PX_ASSERT(exists);
PX_UNUSED(exists);
}
}
#endif