// // 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_SCP_SCENE #define PX_PHYSICS_SCP_SCENE #include "CmPhysXCommon.h" #include "PxPhysXConfig.h" #include "PxScene.h" #include "PxSceneDesc.h" #include "PxSimulationEventCallback.h" #include "PsPool.h" #include "PsHashSet.h" #include "CmRenderOutput.h" #include "CmTask.h" #include "CmFlushPool.h" #include "CmPreallocatingPool.h" #include "CmBitMap.h" #include "ScIterators.h" #include "PxsMaterialManager.h" #include "PxvManager.h" #include "ScBodyCore.h" #include "PxArticulationBase.h" #define PX_MAX_DOMINANCE_GROUP 32 class OverlapFilterTask; namespace physx { // PT: TODO: move INVALID_FILTER_PAIR_INDEX out of public API struct PxFilterInfo { PX_FORCE_INLINE PxFilterInfo() : filterFlags(0), pairFlags(0), filterPairIndex(INVALID_FILTER_PAIR_INDEX) {} PX_FORCE_INLINE PxFilterInfo(PxFilterFlags filterFlags_) : filterFlags(filterFlags_), pairFlags(0), filterPairIndex(INVALID_FILTER_PAIR_INDEX) {} PxFilterFlags filterFlags; PxPairFlags pairFlags; PxU32 filterPairIndex; }; struct PxTriggerPair; class PxsContext; class PxsIslandManager; class PxsSimulationController; class PxsSimulationControllerCallback; class PxsMemoryManager; #if PX_SUPPORT_GPU_PHYSX class PxsKernelWranglerManager; class PxsHeapMemoryAllocatorManager; #endif namespace IG { class SimpleIslandManager; } class PxsCCDContext; namespace Cm { class IDPool; } namespace Bp { class AABBManager; class BroadPhase; class BoundsArray; } namespace Sq { typedef PxU32 PrunerHandle; // PT: we should get this from SqPruner.h but it cannot be included from here } namespace Dy { class ArticulationV; class Context; } namespace Sc { class ActorSim; class ElementSim; class Interaction; class ShapeCore; class RigidCore; class StaticCore; class ConstraintCore; class MaterialCore; class ArticulationCore; class ArticulationJointCore; class LLArticulationPool; class LLArticulationRCPool; class BodyCore; class NPhaseCore; class Client; class ConstraintInteraction; class BodySim; class ShapeSim; class RigidSim; class StaticSim; class ConstraintSim; struct ConstraintGroupNode; class ConstraintProjectionManager; struct TriggerPairExtraData; class ObjectIDTracker; class ActorPairReport; class ContactStreamManager; class SqBoundsManager; class ShapeInteraction; class ElementInteractionMarker; class ArticulationSim; class SimStats; struct SimStateData; struct BatchInsertionState { BodySim* bodySim; StaticSim*staticSim; ShapeSim* shapeSim; ptrdiff_t staticActorOffset; ptrdiff_t staticShapeTableOffset; ptrdiff_t dynamicActorOffset; ptrdiff_t dynamicShapeTableOffset; ptrdiff_t shapeOffset; }; struct BatchRemoveState { Ps::InlineArray bufferedShapes; Ps::InlineArray removedShapes; }; struct InteractionType { enum Enum { eOVERLAP = 0, // corresponds to ShapeInteraction eTRIGGER, // corresponds to TriggerInteraction eMARKER, // corresponds to ElementInteractionMarker eTRACKED_IN_SCENE_COUNT, // not a real type, interactions above this limit are tracked in the scene eCONSTRAINTSHADER, // corresponds to ConstraintInteraction eARTICULATION, // corresponds to ArticulationJointSim eINVALID }; }; struct SceneInternalFlag { enum Enum { eSCENE_SIP_STATES_DIRTY_DOMINANCE = (1<<1), eSCENE_SIP_STATES_DIRTY_VISUALIZATION = (1<<2), eSCENE_DEFAULT = 0 }; }; struct SimulationStage { enum Enum { eCOMPLETE, eCOLLIDE, eFETCHCOLLIDE, eADVANCE, eFETCHRESULT }; }; // PT: TODO: revisit the need for a virtual interface struct SqBoundsSync { virtual void sync(const Sq::PrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds, PxU32 count, const Cm::BitMap& dirtyShapeSimMap) = 0; virtual ~SqBoundsSync() {} }; // PT: TODO: revisit the need for a virtual interface struct SqRefFinder { virtual Sq::PrunerHandle find(const PxRigidBody* body, const PxShape* shape) = 0; virtual ~SqRefFinder() {} }; class Scene : public Ps::UserAllocated { struct SimpleBodyPair { BodySim* body1; BodySim* body2; PxU32 body1ID; PxU32 body2ID; }; PX_NOCOPY(Scene) //--------------------------------------------------------------------------------- // External interface //--------------------------------------------------------------------------------- public: void release(); PX_FORCE_INLINE void setGravity(const PxVec3& g) { mGravity = g; mBodyGravityDirty = true; } PX_FORCE_INLINE PxVec3 getGravity() const { return mGravity; } PX_FORCE_INLINE void setElapsedTime(const PxReal t) { mDt = t; mOneOverDt = t > 0.0f ? 1.0f/t : 0.0f; } void setBounceThresholdVelocity(const PxReal t); PxReal getBounceThresholdVelocity() const; PX_FORCE_INLINE void setPublicFlags(PxSceneFlags flags) { mPublicFlags = flags; } PX_FORCE_INLINE PxSceneFlags getPublicFlags() const { return mPublicFlags; } void setFrictionType(PxFrictionType::Enum model); PxFrictionType::Enum getFrictionType() const; void setPCM(bool enabled); void setContactCache(bool enabled); void addStatic(StaticCore&, void*const *shapes, PxU32 nbShapes, size_t shapePtrOffset, PxBounds3* uninflatedBounds); void removeStatic(StaticCore&, Ps::InlineArray& removedShapes, bool wakeOnLostTouch); void addBody(BodyCore&, void*const *shapes, PxU32 nbShapes, size_t shapePtrOffset, PxBounds3* uninflatedBounds, bool compound); void removeBody(BodyCore&, Ps::InlineArray& removedShapes, bool wakeOnLostTouch); // Batch insertion API. // the bounds generated here are the uninflated bounds for the shapes, *if* they are trigger or sim shapes. // It's up to the caller to ensure the bounds array is big enough. // Some care is required in handling these since sim and SQ tweak the bounds in slightly different ways. void startBatchInsertion(BatchInsertionState&); void addStatic(PxActor* actor, BatchInsertionState&, PxBounds3* outBounds); void addBody(PxActor* actor, BatchInsertionState&, PxBounds3* outBounds, bool compound); void finishBatchInsertion(BatchInsertionState&); // Batch remove helpers PX_FORCE_INLINE void setBatchRemove(BatchRemoveState* bs) { mBatchRemoveState = bs; } PX_FORCE_INLINE BatchRemoveState* getBatchRemove() const { return mBatchRemoveState; } void prefetchForRemove(const BodyCore& ) const; void prefetchForRemove(const StaticCore& ) const; void addConstraint(ConstraintCore&, RigidCore*, RigidCore*); void removeConstraint(ConstraintCore&); void addArticulation(ArticulationCore&, BodyCore& root); void removeArticulation(ArticulationCore&); void addArticulationJoint(ArticulationJointCore&, BodyCore& parent, BodyCore& child); void removeArticulationJoint(ArticulationJointCore&); void addArticulationSimControl(Sc::ArticulationCore& core); void removeArticulationSimControl(Sc::ArticulationCore& core); PxU32 getNbArticulations() const; Sc::ArticulationCore* const* getArticulations(); PxU32 getNbConstraints() const; Sc::ConstraintCore*const * getConstraints(); void initContactsIterator(ContactIterator&, PxsContactManagerOutputIterator&); // Simulation events void setSimulationEventCallback(PxSimulationEventCallback* callback); PxSimulationEventCallback* getSimulationEventCallback() const; // Contact modification void setContactModifyCallback(PxContactModifyCallback* callback); PxContactModifyCallback* getContactModifyCallback() const; void setCCDContactModifyCallback(PxCCDContactModifyCallback* callback); PxCCDContactModifyCallback* getCCDContactModifyCallback() const; void setCCDMaxPasses(PxU32 ccdMaxPasses); PxU32 getCCDMaxPasses() const; // Broad-phase callback PX_FORCE_INLINE void setBroadPhaseCallback(PxBroadPhaseCallback* callback) { mBroadPhaseCallback = callback; } PX_FORCE_INLINE PxBroadPhaseCallback* getBroadPhaseCallback() const { return mBroadPhaseCallback; } // Broad-phase management void finishBroadPhase(PxBaseTask* continuation); void finishBroadPhaseStage2(const PxU32 ccdPass); void preallocateContactManagers(PxBaseTask* continuation); void islandInsertion(PxBaseTask* continuation); void registerContactManagers(PxBaseTask* continuation); void registerInteractions(PxBaseTask* continuation); void registerSceneInteractions(PxBaseTask* continuation); void secondPassNarrowPhase(PxBaseTask* continuation); // Groups void setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance); PxDominanceGroupPair getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const; void setSolverBatchSize(PxU32 solverBatchSize); PxU32 getSolverBatchSize() const; void setSolverArticBatchSize(PxU32 solverBatchSize); PxU32 getSolverArticBatchSize() const; void setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value); PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const; void setVisualizationCullingBox(const PxBounds3& box); const PxBounds3& getVisualizationCullingBox() const; // Run void simulate(PxReal timeStep, PxBaseTask* continuation); void advance(PxReal timeStep, PxBaseTask* continuation); void collide(PxReal timeStep, PxBaseTask* continuation); void endSimulation(); void flush(bool sendPendingReports); void fireBrokenConstraintCallbacks(); void fireTriggerCallbacks(); void fireQueuedContactCallbacks(bool asPartOfFlush); void fireOnAdvanceCallback(); const Ps::Array& getQueuedContactPairHeaders(); bool fireOutOfBoundsCallbacks(); void prepareOutOfBoundsCallbacks(); void postCallbacksPreSync(); void postReportsCleanup(); void fireCallbacksPostSync(); void syncSceneQueryBounds(SqBoundsSync& sync, SqRefFinder& finder); PxU32 getDefaultContactReportStreamBufferSize() const; PxReal getFrictionOffsetThreshold() const; PX_FORCE_INLINE void setLimits(const PxSceneLimits& limits) { mLimits = limits; } PX_FORCE_INLINE const PxSceneLimits& getLimits() const { return mLimits; } void visualizeStartStep(); void visualizeEndStep(); Cm::RenderBuffer& getRenderBuffer(); void setNbContactDataBlocks(PxU32 blockCount); PxU32 getNbContactDataBlocksUsed() const; PxU32 getMaxNbContactDataBlocksUsed() const; PxU32 getMaxNbConstraintDataBlocksUsed() const; void setScratchBlock(void* addr, PxU32 size); // PX_ENABLE_SIM_STATS void getStats(PxSimulationStatistics& stats) const; PX_FORCE_INLINE SimStats& getStatsInternal() { return *mStats; } // PX_ENABLE_SIM_STATS void buildActiveActors(); void buildActiveAndFrozenActors(); PxActor** getActiveActors(PxU32& nbActorsOut); void setActiveActors(PxActor** actors, PxU32 nbActors); PxActor** getFrozenActors(PxU32& nbActorsOut); void finalizeContactStreamAndCreateHeader(PxContactPairHeader& header, const ActorPairReport& aPair, ContactStreamManager& cs, PxU32 removedShapeTestMask); PxClientID createClient(); PX_FORCE_INLINE PxU32 getNbClients() const { return mClients.size(); } PxTaskManager* getTaskManagerPtr() const { return mTaskManager; } PxCudaContextManager* getCudaContextManager() const { return mCudaContextManager; } void shiftOrigin(const PxVec3& shift); PX_FORCE_INLINE Ps::Pool* getSimStateDataPool() { return mSimStateDataPool; } //--------------------------------------------------------------------------------- // Miscellaneous //--------------------------------------------------------------------------------- //internal public methods: public: Scene(const PxSceneDesc& desc, PxU64 contextID); ~Scene() {} //use release() plz. void preAllocate(PxU32 nbStatics, PxU32 nbBodies, PxU32 nbStaticShapes, PxU32 nbDynamicShapes); PX_FORCE_INLINE PxsContext* getLowLevelContext() { return mLLContext; } PX_FORCE_INLINE const PxsContext* getLowLevelContext() const { return mLLContext; } PX_FORCE_INLINE Dy::Context* getDynamicsContext() { return mDynamicsContext; } PX_FORCE_INLINE const Dy::Context* getDynamicsContext() const { return mDynamicsContext; } PX_FORCE_INLINE PxsSimulationController* getSimulationController() { return mSimulationController; } PX_FORCE_INLINE const PxsSimulationController* getSimulationController() const { return mSimulationController; } PX_FORCE_INLINE Bp::AABBManager* getAABBManager() { return mAABBManager; } PX_FORCE_INLINE const Bp::AABBManager* getAABBManager() const { return mAABBManager; } PX_FORCE_INLINE Ps::Array& getCcdBodies() { return mCcdBodies; } /*PX_FORCE_INLINE PxsIslandManager* getIslandManager() { return mIslandManager; } PX_FORCE_INLINE const PxsIslandManager* getIslandManager() const { return mIslandManager; }*/ PX_FORCE_INLINE IG::SimpleIslandManager* getSimpleIslandManager() { return mSimpleIslandManager; } PX_FORCE_INLINE const IG::SimpleIslandManager* getSimpleIslandManager() const { return mSimpleIslandManager; } PX_FORCE_INLINE Sc::SimulationStage::Enum getSimulationStage() const { return mSimulationStage; } PX_FORCE_INLINE void setSimulationStage(Sc::SimulationStage::Enum stage) { mSimulationStage = stage; } void addShape(RigidSim&, ShapeCore&, PxBounds3* uninflatedBounds); void removeShape(ShapeSim&, bool wakeOnLostTouch); void registerShapeInNphase(const ShapeCore& shapeCore); void unregisterShapeFromNphase(const ShapeCore& shapeCore); void notifyNphaseOnUpdateShapeMaterial(const ShapeCore& shapeCore); // Get an array of the active actors. PX_FORCE_INLINE BodyCore*const* getActiveBodiesArray() const { return mActiveBodies.begin(); } PX_FORCE_INLINE PxU32 getNumActiveBodies() const { return mActiveBodies.size(); } PX_FORCE_INLINE BodyCore*const* getActiveCompoundBodiesArray() const { return mActiveCompoundBodies.begin(); } PX_FORCE_INLINE PxU32 getNumActiveCompoundBodies() const { return mActiveCompoundBodies.size(); } PX_FORCE_INLINE PxU32 getNbInteractions(InteractionType::Enum type) const { return mInteractions[type].size(); } PX_FORCE_INLINE PxU32 getNbActiveInteractions(InteractionType::Enum type) const { return mActiveInteractionCount[type]; } // Get all interactions of a certain type PX_FORCE_INLINE Interaction** getInteractions(InteractionType::Enum type) { return mInteractions[type].begin(); } PX_FORCE_INLINE Interaction** getActiveInteractions(InteractionType::Enum type) { return mInteractions[type].begin(); } void registerInteraction(Interaction* interaction, bool active); void unregisterInteraction(Interaction* interaction); void notifyInteractionActivated(Interaction* interaction); void notifyInteractionDeactivated(Interaction* interaction); // for pool management of interaction arrays, a major cause of dynamic allocation void** allocatePointerBlock(PxU32 size); void deallocatePointerBlock(void**, PxU32 size); private: // Get the number of active one-way dominator actors PX_FORCE_INLINE PxU32 getActiveKinematicBodiesCount() const { return mActiveKinematicBodyCount; } // Get an iterator to the active one-way dominator actors PX_FORCE_INLINE BodyCore*const* getActiveKinematicBodies() const { return mActiveBodies.begin(); } // Get the number of active non-kinematic actors PX_FORCE_INLINE PxU32 getActiveDynamicBodiesCount() const { return mActiveBodies.size() - mActiveKinematicBodyCount; } // Get the active non-kinematic actors PX_FORCE_INLINE BodyCore*const* getActiveDynamicBodies() const { return mActiveBodies.begin() + mActiveKinematicBodyCount; } void swapInteractionArrayIndices(PxU32 id1, PxU32 id2, InteractionType::Enum type); public: PX_FORCE_INLINE Cm::BitMap& getDirtyShapeSimMap() { return mDirtyShapeSimMap; } void addToActiveBodyList(BodySim& actor); void addToActiveCompoundBodyList(BodySim& actor); void removeFromActiveBodyList(BodySim& actor); void removeFromActiveCompoundBodyList(BodySim& actor); void swapInActiveBodyList(BodySim& body); // call when an active body gets switched from dynamic to kinematic or vice versa void addToFrozenBodyList(BodySim& actor); void removeFromFrozenBodyList(BodySim& actor); void addBrokenConstraint(Sc::ConstraintCore*); void addActiveBreakableConstraint(Sc::ConstraintSim*, ConstraintInteraction*); void removeActiveBreakableConstraint(Sc::ConstraintSim*); //the Actor should register its top level shapes with these. void removeBody(BodySim&); void raiseSceneFlag(SceneInternalFlag::Enum flag) { mInternalFlags |= flag; } //lists of actors woken up or put to sleep last simulate void onBodyWakeUp(BodySim* body); void onBodySleep(BodySim* body); PX_FORCE_INLINE bool isValid() const { return (mLLContext != NULL); } void addToLostTouchList(BodySim* body1, BodySim* body2); void initDominanceMatrix(); void setCreateContactReports(bool s); PxU32 createAggregate(void* userData, bool selfCollisions); void deleteAggregate(PxU32 id); Dy::ArticulationV* createLLArticulation(Sc::ArticulationSim* sim); void destroyLLArticulation(Dy::ArticulationV&); Ps::Pool* getConstraintInteractionPool() const { return mConstraintInteractionPool; } public: PxBroadPhaseType::Enum getBroadPhaseType() const; bool getBroadPhaseCaps(PxBroadPhaseCaps& caps) const; PxU32 getNbBroadPhaseRegions() const; PxU32 getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex) const; PxU32 addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion); bool removeBroadPhaseRegion(PxU32 handle); void** getOutOfBoundsAggregates(); PxU32 getNbOutOfBoundsAggregates(); void clearOutOfBoundsAggregates(); PX_FORCE_INLINE const PxsMaterialManager& getMaterialManager() const { return mMaterialManager; } PX_FORCE_INLINE PxsMaterialManager& getMaterialManager() { return mMaterialManager; } //material management functions to be called from Scb::Scene void registerMaterialInNP(const PxsMaterialCore& materialCore); void updateMaterialInNP(const PxsMaterialCore& materialCore); void unregisterMaterialInNP(const PxsMaterialCore& materialCore); // Collision filtering void setFilterShaderData(const void* data, PxU32 dataSize); PX_FORCE_INLINE const void* getFilterShaderDataFast() const { return mFilterShaderData; } PX_FORCE_INLINE PxU32 getFilterShaderDataSizeFast() const { return mFilterShaderDataSize; } PX_FORCE_INLINE PxSimulationFilterShader getFilterShaderFast() const { return mFilterShader; } PX_FORCE_INLINE PxSimulationFilterCallback* getFilterCallbackFast() const { return mFilterCallback; } PX_FORCE_INLINE PxPairFilteringMode::Enum getKineKineFilteringMode() const { return mKineKineFilteringMode; } PX_FORCE_INLINE PxPairFilteringMode::Enum getStaticKineFilteringMode() const { return mStaticKineFilteringMode; } PX_FORCE_INLINE PxU32 getTimeStamp() const { return mTimeStamp; } PX_FORCE_INLINE PxU32 getReportShapePairTimeStamp() const { return mReportShapePairTimeStamp; } PX_FORCE_INLINE PxReal getOneOverDt() const { return mOneOverDt; } PX_FORCE_INLINE PxReal getDt() const { return mDt; } PX_FORCE_INLINE const PxVec3& getGravityFast() const { return mGravity; } PX_FORCE_INLINE bool readFlag(SceneInternalFlag::Enum flag) const { return (mInternalFlags & flag) != 0; } PX_FORCE_INLINE bool readPublicFlag(PxSceneFlag::Enum flag) const { return (mPublicFlags & flag); } PX_FORCE_INLINE NPhaseCore* getNPhaseCore() const { return mNPhaseCore; } void checkConstraintBreakage(); PX_FORCE_INLINE Ps::Array& getTriggerBufferExtraData() { return *mTriggerBufferExtraData; } PX_FORCE_INLINE Ps::Array& getTriggerBufferAPI() { return mTriggerBufferAPI; } void reserveTriggerReportBufferSpace(const PxU32 pairCount, PxTriggerPair*& triggerPairBuffer, TriggerPairExtraData*& triggerPairExtraBuffer); PX_FORCE_INLINE ObjectIDTracker& getRigidIDTracker() { return *mRigidIDTracker; } PX_FORCE_INLINE ObjectIDTracker& getShapeIDTracker() { return *mShapeIDTracker; } PX_FORCE_INLINE void markReleasedBodyIDForLostTouch(PxU32 id) { mLostTouchPairsDeletedBodyIDs.growAndSet(id); } void resizeReleasedBodyIDMaps(PxU32 maxActors, PxU32 numActors); PX_FORCE_INLINE StaticSim& getStaticAnchor() { return *mStaticAnchor; } PX_FORCE_INLINE ConstraintProjectionManager& getProjectionManager() { return *mProjectionManager; } PX_FORCE_INLINE Bp::BoundsArray& getBoundsArray() const { return *mBoundsArray; } PX_FORCE_INLINE void updateContactDistance(PxU32 idx, PxReal distance) { (*mContactDistance)[idx] = distance; mHasContactDistanceChanged = true; } PX_FORCE_INLINE SqBoundsManager& getSqBoundsManager() const { return *mSqBoundsManager; } PX_FORCE_INLINE PxReal getVisualizationScale() const { return mVisualizationScale; } // This is actually redundant but makes checks whether debug visualization is enabled faster PX_FORCE_INLINE BodyCore* const* getSleepBodiesArray(PxU32& count) { count = mSleepBodies.size(); return mSleepBodies.getEntries(); } PX_FORCE_INLINE PxTaskManager& getTaskManager() const { PX_ASSERT(mTaskManager); return *mTaskManager; } Cm::FlushPool* getFlushPool(); PX_FORCE_INLINE bool getStabilizationEnabled() const { return mEnableStabilization; } PX_FORCE_INLINE void setPostSolverVelocityNeeded() { mContactReportsNeedPostSolverVelocity = true; } ObjectIDTracker& getConstraintIDTracker() { return *mConstraintIDTracker; } void* allocateConstraintBlock(PxU32 size); void deallocateConstraintBlock(void* addr, PxU32 size); PX_INLINE ObjectIDTracker& getElementIDPool() { return *mElementIDPool; } PX_FORCE_INLINE Cm::BitMap& getVelocityModifyMap() { return mVelocityModifyMap; } void stepSetupCollide(PxBaseTask* continuation);//This is very important to guarantee thread safty in the collide PX_FORCE_INLINE void addToPosePreviewList(BodySim& b) { PX_ASSERT(!mPosePreviewBodies.contains(&b)); mPosePreviewBodies.insert(&b); } PX_FORCE_INLINE void removeFromPosePreviewList(BodySim& b) { PX_ASSERT(mPosePreviewBodies.contains(&b)); mPosePreviewBodies.erase(&b); } #if PX_DEBUG PX_FORCE_INLINE bool isInPosePreviewList(BodySim& b) const { return mPosePreviewBodies.contains(&b); } #endif PX_FORCE_INLINE void setSpeculativeCCDRigidBody(const PxU32 index) { mSpeculativeCCDRigidBodyBitMap.growAndSet(index); } PX_FORCE_INLINE void resetSpeculativeCCDRigidBody(const PxU32 index) { if(index < mSpeculativeCCDRigidBodyBitMap.size()) mSpeculativeCCDRigidBodyBitMap.reset(index); } PX_FORCE_INLINE void setSpeculativeCCDArticulationLink(const PxU32 index) { mSpeculativeCDDArticulationBitMap.growAndSet(index); } PX_FORCE_INLINE void resetSpeculativeCCDArticulationLink(const PxU32 index) { if(index < mSpeculativeCDDArticulationBitMap.size()) mSpeculativeCDDArticulationBitMap.reset(index); } PX_FORCE_INLINE PxU64 getContextId() const { return mContextId; } PX_FORCE_INLINE bool isUsingGpuRigidBodies() const { return mUseGpuRigidBodies; } // statistics counters increase/decrease PX_FORCE_INLINE void increaseNumKinematicsCounter() { mNbRigidKinematic++; } PX_FORCE_INLINE void decreaseNumKinematicsCounter() { mNbRigidKinematic--; } PX_FORCE_INLINE void increaseNumDynamicsCounter() { mNbRigidDynamics++; } PX_FORCE_INLINE void decreaseNumDynamicsCounter() { mNbRigidDynamics--; } //internal private methods: private: void releaseConstraints(bool endOfScene); PX_INLINE void clearBrokenConstraintBuffer(); ///////////////////////////////////////////////////////////// void prepareCollide(); void collideStep(PxBaseTask* continuation); void advanceStep(PxBaseTask* continuation); // subroutines of collideStep/solveStep: void kinematicsSetup(PxBaseTask* continuation); void stepSetupSolve(PxBaseTask* continuation); //void stepSetupSimulate(); void fetchPatchEvents(PxBaseTask*); void processNarrowPhaseTouchEvents(); void processNarrowPhaseTouchEventsStage2(PxBaseTask*); void setEdgesConnected(PxBaseTask*); void processNarrowPhaseLostTouchEvents(PxBaseTask*); void processNarrowPhaseLostTouchEventsIslands(PxBaseTask*); void processLostTouchPairs(); void integrateKinematicPose(); void updateKinematicCached(PxBaseTask* task); void beforeSolver(PxBaseTask* continuation); void checkForceThresholdContactEvents(const PxU32 ccdPass); void processCallbacks(bool pendingReportsOnly = false); void endStep(); private: PX_FORCE_INLINE void putObjectsToSleep(PxU32 infoFlag); PX_FORCE_INLINE void putInteractionsToSleep(); PX_FORCE_INLINE void wakeObjectsUp(PxU32 infoFlag); void collectPostSolverVelocitiesBeforeCCD(); void clearSleepWakeBodies(void); PX_INLINE void cleanUpSleepBodies(); PX_INLINE void cleanUpWokenBodies(); PX_INLINE void cleanUpSleepOrWokenBodies(Ps::CoalescedHashSet& bodyList, PxU32 removeFlag, bool& validMarker); //internal variables: private: // Material manager PX_ALIGN(16, PxsMaterialManager mMaterialManager); PxU64 mContextId; Ps::Array mActiveBodies; // Sorted: kinematic before dynamic PxU32 mActiveKinematicBodyCount; // Number of active kinematics. This is also the index in mActiveBodies where the active dynamic bodies start. Ps::Array mActiveCompoundBodies; Ps::Array mInteractions[InteractionType::eTRACKED_IN_SCENE_COUNT]; PxU32 mActiveInteractionCount[InteractionType::eTRACKED_IN_SCENE_COUNT]; // Interactions with id < activeInteractionCount are active template struct Block { PxU8 mem[sizeof(T)*size]; Block() {} // get around VS warning C4345, otherwise useless }; typedef Block PointerBlock8; typedef Block PointerBlock16; typedef Block PointerBlock32; Ps::Pool mPointerBlock8Pool; Ps::Pool mPointerBlock16Pool; Ps::Pool mPointerBlock32Pool; PxsContext* mLLContext; Bp::AABBManager* mAABBManager; Bp::BroadPhase* mBP; PxsCCDContext* mCCDContext; PxI32 mNumFastMovingShapes; PxU32 mCCDPass; //PxsIslandManager* mIslandManager; IG::SimpleIslandManager* mSimpleIslandManager; Dy::Context* mDynamicsContext; PxsMemoryManager* mMemoryManager; #if PX_SUPPORT_GPU_PHYSX PxsKernelWranglerManager* mGpuWranglerManagers; PxsHeapMemoryAllocatorManager* mHeapMemoryAllocationManager; #endif PxsSimulationController* mSimulationController; PxsSimulationControllerCallback* mSimulationControllerCallback; PxSceneLimits mLimits; PxVec3 mGravity; //!< Gravity vector PxU32 mBodyGravityDirty; // Set to true before body->updateForces() when the mGravity has changed Ps::Array mQueuedContactPairHeaders; //time: //constants set with setTiming(): PxReal mDt; //delta time for current step. PxReal mOneOverDt; //inverse of dt. //stepping / counters: PxU32 mTimeStamp; //Counts number of steps. PxU32 mReportShapePairTimeStamp; //Timestamp for refreshing the shape pair report structure. Updated before delayed shape/actor deletion and before CCD passes. //containers: // Those ones contain shape ptrs from Actor, i.e. compound level, not subparts Ps::CoalescedHashSet mConstraints; Sc::ConstraintProjectionManager* mProjectionManager; Bp::BoundsArray* mBoundsArray; Ps::Array* mContactDistance; bool mHasContactDistanceChanged; SqBoundsManager* mSqBoundsManager; Ps::Array mCcdBodies; Ps::Array mProjectedBodies; Ps::Array mTriggerBufferAPI; Ps::Array* mTriggerBufferExtraData; PxU32 mRemovedShapeCountAtSimStart; // counter used to detect whether there have been buffered shape removals Ps::CoalescedHashSet mArticulations; Ps::Array mBrokenConstraints; Ps::CoalescedHashSet mActiveBreakableConstraints; // pools for joint buffers // Fixed joint is 92 bytes, D6 is 364 bytes right now. So these three pools cover all the internal cases typedef Block MemBlock128; typedef Block MemBlock256; typedef Block MemBlock384; Ps::Pool2 mMemBlock128Pool; Ps::Pool2 mMemBlock256Pool; Ps::Pool2 mMemBlock384Pool; // broad phase data: NPhaseCore* mNPhaseCore; // Collision filtering void* mFilterShaderData; PxU32 mFilterShaderDataSize; PxU32 mFilterShaderDataCapacity; PxSimulationFilterShader mFilterShader; PxSimulationFilterCallback* mFilterCallback; PxPairFilteringMode::Enum mKineKineFilteringMode; PxPairFilteringMode::Enum mStaticKineFilteringMode; Ps::CoalescedHashSet mSleepBodies; Ps::CoalescedHashSet mWokeBodies; bool mWokeBodyListValid; bool mSleepBodyListValid; bool mEnableStabilization; Ps::Array mClients; //an array of transform arrays, one for each client. Ps::Array mActiveActors; Ps::Array mFrozenActors; Ps::Array mClientPosePreviewBodies; // buffer for bodies that requested early report of the integrated pose (eENABLE_POSE_INTEGRATION_PREVIEW). // This buffer gets exposed to users. Is officially accessible from PxSimulationEventCallback::onAdvance() // until the next simulate()/advance(). Ps::Array mClientPosePreviewBuffer; // buffer of newly integrated poses for the bodies that requested a preview. This buffer gets exposed // to users. PxSimulationEventCallback* mSimulationEventCallback; PxBroadPhaseCallback* mBroadPhaseCallback; SimStats* mStats; PxU32 mInternalFlags; //!< Combination of ::SceneFlag PxSceneFlags mPublicFlags; //copy of PxSceneDesc::flags, of type PxSceneFlag ObjectIDTracker* mConstraintIDTracker; ObjectIDTracker* mShapeIDTracker; ObjectIDTracker* mRigidIDTracker; ObjectIDTracker* mElementIDPool; StaticSim* mStaticAnchor; Cm::PreallocatingPool* mShapeSimPool; Cm::PreallocatingPool* mStaticSimPool; Cm::PreallocatingPool* mBodySimPool; Ps::Pool* mConstraintSimPool; LLArticulationPool* mLLArticulationPool; LLArticulationRCPool* mLLArticulationRCPool; Ps::Pool* mConstraintInteractionPool; Ps::Pool* mSimStateDataPool; BatchRemoveState* mBatchRemoveState; Ps::Array mLostTouchPairs; Cm::BitMap mLostTouchPairsDeletedBodyIDs; // Need to know which bodies have been deleted when processing the lost touch pair list. // Can't use the existing rigid object ID tracker class since this map needs to be cleared at // another point in time. Cm::BitMap mVelocityModifyMap; Ps::Array mTouchFoundEvents; Ps::Array mTouchLostEvents; Ps::Array mFoundPatchManagers; Ps::Array mLostPatchManagers; Ps::Array mOutOfBoundsIDs; Cm::BitMap mDirtyShapeSimMap; PxU32 mDominanceBitMatrix[PX_MAX_DOMINANCE_GROUP]; PxReal mVisualizationScale; // Redundant but makes checks whether debug visualization is enabled faster bool mVisualizationParameterChanged; // statics: PxU32 mNbRigidStatics; PxU32 mNbRigidDynamics; PxU32 mNbRigidKinematic; PxU32 mNbGeometries[PxGeometryType::eGEOMETRY_COUNT]; PxU32 mNumDeactivatingNodes[2]; // task decomposition void preBroadPhase(PxBaseTask* continuation); void broadPhase(PxBaseTask* continuation); void postBroadPhase(PxBaseTask* continuation); void postBroadPhaseContinuation(PxBaseTask* continuation); void preRigidBodyNarrowPhase(PxBaseTask* continuation); void postBroadPhaseStage2(PxBaseTask* continuation); void postBroadPhaseStage3(PxBaseTask* continuation); void rigidBodyNarrowPhase(PxBaseTask* continuation); void unblockNarrowPhase(PxBaseTask* continuation); void islandGen(PxBaseTask* continuation); void processLostSolverPatches(PxBaseTask* continuation); void postIslandGen(PxBaseTask* continuation); void processTriggerInteractions(PxBaseTask* continuation); void solver(PxBaseTask* continuation); void updateBodiesAndShapes(PxBaseTask* continuation); void updateSimulationController(PxBaseTask* continuation); void updateDynamics(PxBaseTask* continuation); void processLostContacts(PxBaseTask*); void processLostContacts2(PxBaseTask*); void processLostContacts3(PxBaseTask*); void destroyManagers(PxBaseTask*); void lostTouchReports(PxBaseTask*); void unregisterInteractions(PxBaseTask*); void postThirdPassIslandGen(PxBaseTask*); void postSolver(PxBaseTask* continuation); void constraintProjection(PxBaseTask* continuation); void afterIntegration(PxBaseTask* continuation); // performs sleep check, for instance void postCCDPass(PxBaseTask* continuation); void ccdBroadPhaseAABB(PxBaseTask* continuation); void ccdBroadPhase(PxBaseTask* continuation); void updateCCDMultiPass(PxBaseTask* continuation); void updateCCDSinglePass(PxBaseTask* continuation); void updateCCDSinglePassStage2(PxBaseTask* continuation); void updateCCDSinglePassStage3(PxBaseTask* continuation); void finalizationPhase(PxBaseTask* continuation); void postNarrowPhase(PxBaseTask* continuation); void addShapes(void *const* shapes, PxU32 nbShapes, size_t ptrOffset, RigidSim& sim, PxBounds3* outBounds); void removeShapes(RigidSim& , Ps::InlineArray& , Ps::InlineArray&, bool wakeOnLostTouch); private: void addShapes(void *const* shapes, PxU32 nbShapes, size_t ptrOffset, RigidSim& sim, ShapeSim*& prefetchedShapeSim, PxBounds3* outBounds); Cm::DelegateTask mSecondPassNarrowPhase; Cm::DelegateFanoutTask mPostNarrowPhase; Cm::DelegateFanoutTask mFinalizationPhase; Cm::DelegateTask mUpdateCCDMultiPass; //multi-pass ccd stuff Ps::Array > mUpdateCCDSinglePass; Ps::Array > mUpdateCCDSinglePass2; Ps::Array > mUpdateCCDSinglePass3; Ps::Array > mCCDBroadPhaseAABB; Ps::Array > mCCDBroadPhase; Ps::Array > mPostCCDPass; PxU32 mCurrentCCDTask; Cm::DelegateTask mAfterIntegration; Cm::DelegateTask mConstraintProjection; Cm::DelegateTask mPostSolver; Cm::DelegateTask mSolver; Cm::DelegateTask mUpdateBodiesAndShapes; Cm::DelegateTask mUpdateSimulationController; Cm::DelegateTask mUpdateDynamics; Cm::DelegateTask mProcessLostContactsTask; Cm::DelegateTask mProcessLostContactsTask2; Cm::DelegateTask mProcessLostContactsTask3; Cm::DelegateTask mDestroyManagersTask; Cm::DelegateTask mLostTouchReportsTask; Cm::DelegateTask mUnregisterInteractionsTask; Cm::DelegateTask mProcessNarrowPhaseLostTouchTasks; Cm::DelegateTask mProcessNPLostTouchEvents; Cm::DelegateTask mPostThirdPassIslandGenTask; Cm::DelegateTask mPostIslandGen; Cm::DelegateTask mIslandGen; Cm::DelegateTask mPreRigidBodyNarrowPhase; Cm::DelegateTask mSetEdgesConnectedTask; Cm::DelegateTask mFetchPatchEventsTask; Cm::DelegateTask mProcessLostPatchesTask; Cm::DelegateTask mRigidBodyNarrowPhase; Cm::DelegateTask mRigidBodyNPhaseUnlock; Cm::DelegateTask mPostBroadPhase; Cm::DelegateTask mPostBroadPhaseCont; Cm::DelegateTask mPostBroadPhase2; Cm::DelegateFanoutTask mPostBroadPhase3; Cm::DelegateTask mPreallocateContactManagers; Cm::DelegateTask mIslandInsertion; Cm::DelegateTask mRegisterContactManagers; Cm::DelegateTask mRegisterInteractions; Cm::DelegateTask mRegisterSceneInteractions; Cm::DelegateTask mBroadPhase; Cm::DelegateTask mAdvanceStep; Cm::DelegateTask mCollideStep; Cm::FlushPool mTaskPool; PxTaskManager* mTaskManager; PxCudaContextManager* mCudaContextManager; bool mContactReportsNeedPostSolverVelocity; bool mUseGpuRigidBodies; SimulationStage::Enum mSimulationStage; ConstraintGroupNode** mTmpConstraintGroupRootBuffer; // temporary list of constraint group roots, used for constraint projection Ps::CoalescedHashSet mPosePreviewBodies; // list of bodies that requested early report of the integrated pose (eENABLE_POSE_INTEGRATION_PREVIEW). Ps::Array mPreallocatedContactManagers; Ps::Array mPreallocatedShapeInteractions; Ps::Array mPreallocatedInteractionMarkers; OverlapFilterTask* mOverlapFilterTaskHead; Ps::Array mFilterInfo; Cm::BitMap mSpeculativeCCDRigidBodyBitMap; Cm::BitMap mSpeculativeCDDArticulationBitMap; }; bool activateInteraction(Sc::Interaction* interaction, void* data); bool deactivateInteraction(Sc::Interaction* interaction); } // namespace Sc } #endif