| 1 | // |
| 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions |
| 4 | // are met: |
| 5 | // * Redistributions of source code must retain the above copyright |
| 6 | // notice, this list of conditions and the following disclaimer. |
| 7 | // * Redistributions in binary form must reproduce the above copyright |
| 8 | // notice, this list of conditions and the following disclaimer in the |
| 9 | // documentation and/or other materials provided with the distribution. |
| 10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
| 11 | // contributors may be used to endorse or promote products derived |
| 12 | // from this software without specific prior written permission. |
| 13 | // |
| 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
| 15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | // |
| 26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
| 27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
| 28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
| 29 | |
| 30 | |
| 31 | #ifndef PXS_CONTEXT_H |
| 32 | #define PXS_CONTEXT_H |
| 33 | |
| 34 | #include "PxVisualizationParameter.h" |
| 35 | #include "PxSceneDesc.h" |
| 36 | |
| 37 | #include "CmPool.h" |
| 38 | |
| 39 | #include "PxvNphaseImplementationContext.h" |
| 40 | #include "PxvSimStats.h" |
| 41 | #include "PxsContactManager.h" |
| 42 | #include "PxcNpBatch.h" |
| 43 | #include "PxcConstraintBlockStream.h" |
| 44 | #include "PxcNpCacheStreamPair.h" |
| 45 | #include "PxcNpMemBlockPool.h" |
| 46 | #include "CmRenderOutput.h" |
| 47 | #include "CmUtils.h" |
| 48 | #include "CmTask.h" |
| 49 | |
| 50 | #include "PxContactModifyCallback.h" |
| 51 | |
| 52 | #include "PxsTransformCache.h" |
| 53 | #include "GuPersistentContactManifold.h" |
| 54 | #include "DyArticulation.h" |
| 55 | |
| 56 | |
| 57 | #if PX_SUPPORT_GPU_PHYSX |
| 58 | namespace physx |
| 59 | { |
| 60 | class PxCudaContextManager; |
| 61 | } |
| 62 | #endif |
| 63 | |
| 64 | namespace physx |
| 65 | { |
| 66 | |
| 67 | class PxsRigidBody; |
| 68 | struct PxcConstraintBlock; |
| 69 | class PxsMaterialManager; |
| 70 | class PxsCCDContext; |
| 71 | struct PxsContactManagerOutput; |
| 72 | struct PxvContactManagerTouchEvent; |
| 73 | |
| 74 | namespace Cm |
| 75 | { |
| 76 | class FlushPool; |
| 77 | } |
| 78 | |
| 79 | namespace IG |
| 80 | { |
| 81 | class SimpleIslandManager; |
| 82 | typedef PxU32 EdgeIndex; |
| 83 | } |
| 84 | |
| 85 | enum PxsTouchEventCount |
| 86 | { |
| 87 | PXS_LOST_TOUCH_COUNT = 0, |
| 88 | PXS_NEW_TOUCH_COUNT = 1, |
| 89 | PXS_CCD_RETOUCH_COUNT = 2, // pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already |
| 90 | // (but they could have lost touch in between) |
| 91 | PXS_PATCH_FOUND_COUNT = 3, |
| 92 | PXS_PATCH_LOST_COUNT = 4, |
| 93 | PXS_TOUCH_EVENT_COUNT = 5 |
| 94 | }; |
| 95 | |
| 96 | class PxsContext : public Ps::UserAllocated, public PxcNpContext |
| 97 | { |
| 98 | PX_NOCOPY(PxsContext) |
| 99 | public: |
| 100 | PxsContext( const PxSceneDesc& desc, PxTaskManager*, Cm::FlushPool&, PxCudaContextManager*, PxU64 contextID); |
| 101 | ~PxsContext(); |
| 102 | |
| 103 | void removeRigidBody(PxsRigidBody&); |
| 104 | |
| 105 | Dy::Articulation* createArticulation(); |
| 106 | void destroyArticulation(Dy::Articulation&); |
| 107 | |
| 108 | void createTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback); |
| 109 | |
| 110 | PxsContactManager* createContactManager(PxsContactManager* contactManager, const bool useCCD); |
| 111 | void createCache(Gu::Cache& cache, PxsContactManager* cm, PxU8 geomType0, PxU8 geomType1); |
| 112 | void destroyCache(Gu::Cache& cache); |
| 113 | void destroyContactManager(PxsContactManager* cm); |
| 114 | |
| 115 | |
| 116 | PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; } |
| 117 | |
| 118 | // Collision properties |
| 119 | PX_FORCE_INLINE PxContactModifyCallback* getContactModifyCallback() const { return mContactModifyCallback; } |
| 120 | PX_FORCE_INLINE void setContactModifyCallback(PxContactModifyCallback* c) { mContactModifyCallback = c; mNpImplementationContext->setContactModifyCallback(c);} |
| 121 | |
| 122 | |
| 123 | // resource-related |
| 124 | void setScratchBlock(void* addr, PxU32 size); |
| 125 | |
| 126 | void setContactDistance(Ps::Array<PxReal, Ps::VirtualAllocator>* contactDistance); |
| 127 | |
| 128 | // Task-related |
| 129 | void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation); |
| 130 | void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation); |
| 131 | void fetchUpdateContactManager(); |
| 132 | void swapStreams(); |
| 133 | |
| 134 | void resetThreadContexts(); |
| 135 | |
| 136 | // Manager status change |
| 137 | bool getManagerTouchEventCount(int* newTouch, int* lostTouch, int* ccdTouch) const; |
| 138 | bool fillManagerTouchEvents( |
| 139 | PxvContactManagerTouchEvent* newTouch, PxI32& newTouchCount, |
| 140 | PxvContactManagerTouchEvent* lostTouch, PxI32& lostTouchCount, |
| 141 | PxvContactManagerTouchEvent* ccdTouch, PxI32& ccdTouchCount); |
| 142 | |
| 143 | PX_FORCE_INLINE void getManagerPatchEventCount(PxU32& foundPatch, PxU32& lostPatch) const { foundPatch = mCMTouchEventCount[PXS_PATCH_FOUND_COUNT]; lostPatch = mCMTouchEventCount[PXS_PATCH_LOST_COUNT]; } |
| 144 | bool fillManagerPatchChangedEvents( |
| 145 | PxsContactManager** foundPatch, PxU32& foundPatchCount, |
| 146 | PxsContactManager** lostPatch, PxU32& lostPatchCount); |
| 147 | |
| 148 | void beginUpdate(); |
| 149 | |
| 150 | // PX_ENABLE_SIM_STATS |
| 151 | PX_FORCE_INLINE PxvSimStats& getSimStats() { return mSimStats; } |
| 152 | PX_FORCE_INLINE const PxvSimStats& getSimStats() const { return mSimStats; } |
| 153 | |
| 154 | PX_FORCE_INLINE Cm::FlushPool& getTaskPool() const { return mTaskPool; } |
| 155 | PX_FORCE_INLINE Cm::RenderBuffer& getRenderBuffer() { return mRenderBuffer; } |
| 156 | |
| 157 | PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const; |
| 158 | void setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value); |
| 159 | |
| 160 | PX_FORCE_INLINE void setVisualizationCullingBox(const PxBounds3& box) { mVisualizationCullingBox = box; } |
| 161 | PX_FORCE_INLINE const PxBounds3& getVisualizationCullingBox()const { return mVisualizationCullingBox; } |
| 162 | |
| 163 | PX_FORCE_INLINE PxReal getRenderScale() const { return mVisualizationParams[PxVisualizationParameter::eSCALE]; } |
| 164 | Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); } |
| 165 | PX_FORCE_INLINE bool getPCM() const { return mPCM; } |
| 166 | PX_FORCE_INLINE bool getContactCacheFlag() const { return mContactCache; } |
| 167 | PX_FORCE_INLINE bool getCreateAveragePoint() const { return mCreateAveragePoint; } |
| 168 | |
| 169 | // general stuff |
| 170 | void shiftOrigin(const PxVec3& shift); |
| 171 | |
| 172 | void setCreateContactStream(bool to); |
| 173 | PX_FORCE_INLINE void setPCM(bool enabled) { mPCM = enabled; } |
| 174 | PX_FORCE_INLINE void setContactCache(bool enabled) { mContactCache = enabled; } |
| 175 | |
| 176 | PX_FORCE_INLINE PxcScratchAllocator& getScratchAllocator() { return mScratchAllocator; } |
| 177 | PX_FORCE_INLINE PxsTransformCache& getTransformCache() { return *mTransformCache; } |
| 178 | PX_FORCE_INLINE PxReal* getContactDistance() { return mContactDistance->begin(); } |
| 179 | |
| 180 | PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseImplementationContext() const |
| 181 | { |
| 182 | return mNpImplementationContext; |
| 183 | } |
| 184 | |
| 185 | PX_FORCE_INLINE void setNphaseImplementationContext(PxvNphaseImplementationContext* ctx) |
| 186 | { |
| 187 | mNpImplementationContext = ctx; |
| 188 | } |
| 189 | |
| 190 | PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseFallbackImplementationContext() const |
| 191 | { |
| 192 | return mNpFallbackImplementationContext; |
| 193 | } |
| 194 | |
| 195 | PX_FORCE_INLINE void setNphaseFallbackImplementationContext(PxvNphaseImplementationContext* ctx) |
| 196 | { |
| 197 | mNpFallbackImplementationContext = ctx; |
| 198 | } |
| 199 | |
| 200 | PxU32 getTotalCompressedContactSize() const { return mTotalCompressedCacheSize; } |
| 201 | PxU32 getMaxPatchCount() const { return mMaxPatches; } |
| 202 | |
| 203 | PX_FORCE_INLINE PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>& getNpThreadContextPool() |
| 204 | { |
| 205 | return mNpThreadContextPool; |
| 206 | } |
| 207 | |
| 208 | PX_FORCE_INLINE PxcNpThreadContext* getNpThreadContext() |
| 209 | { |
| 210 | // We may want to conditional compile to exclude this on single threaded implementations |
| 211 | // if it is determined to be a performance hit. |
| 212 | return mNpThreadContextPool.get(); |
| 213 | } |
| 214 | |
| 215 | PX_FORCE_INLINE void putNpThreadContext(PxcNpThreadContext* threadContext) |
| 216 | { mNpThreadContextPool.put(item: threadContext); } |
| 217 | PX_FORCE_INLINE Ps::Mutex& getLock() { return mLock; } |
| 218 | |
| 219 | PX_FORCE_INLINE PxTaskManager& getTaskManager() |
| 220 | { |
| 221 | PX_ASSERT(mTaskManager); |
| 222 | return *mTaskManager; |
| 223 | } |
| 224 | |
| 225 | PX_FORCE_INLINE PxCudaContextManager* getCudaContextManager() |
| 226 | { |
| 227 | return mCudaContextManager; |
| 228 | } |
| 229 | |
| 230 | PX_FORCE_INLINE void clearManagerTouchEvents(); |
| 231 | |
| 232 | PX_FORCE_INLINE Cm::PoolList<PxsContactManager, PxsContext>& getContactManagerPool() |
| 233 | { |
| 234 | return this->mContactManagerPool; |
| 235 | } |
| 236 | |
| 237 | PX_FORCE_INLINE void setActiveContactManager(const PxsContactManager* manager) |
| 238 | { |
| 239 | const PxU32 index = manager->getIndex(); |
| 240 | if (index >= mActiveContactManager.size()) |
| 241 | { |
| 242 | PxU32 newSize = (2 * index + 256)&~255; |
| 243 | mActiveContactManager.resize(newBitCount: newSize); |
| 244 | } |
| 245 | mActiveContactManager.set(index); |
| 246 | |
| 247 | //Record any pairs that have CCD enabled! |
| 248 | if (manager->getCCD()) |
| 249 | { |
| 250 | if (index >= mActiveContactManagersWithCCD.size()) |
| 251 | { |
| 252 | PxU32 newSize = (2 * index + 256)&~255; |
| 253 | mActiveContactManagersWithCCD.resize(newBitCount: newSize); |
| 254 | } |
| 255 | mActiveContactManagersWithCCD.set(index); |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | |
| 260 | private: |
| 261 | void mergeCMDiscreteUpdateResults(PxBaseTask* continuation); |
| 262 | |
| 263 | PxU32 mIndex; |
| 264 | |
| 265 | // Threading |
| 266 | PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext> |
| 267 | mNpThreadContextPool; |
| 268 | |
| 269 | // Contact managers |
| 270 | Cm::PoolList<PxsContactManager, PxsContext> mContactManagerPool; |
| 271 | Ps::Pool<Gu::LargePersistentContactManifold> mManifoldPool; |
| 272 | Ps::Pool<Gu::SpherePersistentContactManifold> mSphereManifoldPool; |
| 273 | |
| 274 | Cm::BitMap mActiveContactManager; |
| 275 | Cm::BitMap mActiveContactManagersWithCCD; //KS - adding to filter any pairs that had a touch |
| 276 | Cm::BitMap mContactManagersWithCCDTouch; //KS - adding to filter any pairs that had a touch |
| 277 | Cm::BitMap mContactManagerTouchEvent; |
| 278 | Cm::BitMap mContactManagerPatchChangeEvent; |
| 279 | PxU32 mCMTouchEventCount[PXS_TOUCH_EVENT_COUNT]; |
| 280 | |
| 281 | Ps::Mutex mLock; |
| 282 | |
| 283 | |
| 284 | |
| 285 | PxContactModifyCallback* mContactModifyCallback; |
| 286 | |
| 287 | // narrowphase platform-dependent implementations support |
| 288 | PxvNphaseImplementationContext* mNpImplementationContext; |
| 289 | PxvNphaseImplementationContext* mNpFallbackImplementationContext; |
| 290 | |
| 291 | |
| 292 | // debug rendering (CS TODO: MS would like to have these wrapped into a class) |
| 293 | PxReal mVisualizationParams[PxVisualizationParameter::eNUM_VALUES]; |
| 294 | |
| 295 | PxBounds3 mVisualizationCullingBox; |
| 296 | |
| 297 | PxTaskManager* mTaskManager; |
| 298 | Cm::FlushPool& mTaskPool; |
| 299 | |
| 300 | PxCudaContextManager* mCudaContextManager; |
| 301 | |
| 302 | // PxU32 mTouchesLost; |
| 303 | // PxU32 mTouchesFound; |
| 304 | |
| 305 | // PX_ENABLE_SIM_STATS |
| 306 | PxvSimStats mSimStats; |
| 307 | bool mPCM; |
| 308 | bool mContactCache; |
| 309 | bool mCreateAveragePoint; |
| 310 | |
| 311 | PxsTransformCache* mTransformCache; |
| 312 | Ps::Array<PxReal, Ps::VirtualAllocator>* mContactDistance; |
| 313 | |
| 314 | |
| 315 | PxU32 mMaxPatches; |
| 316 | PxU32 mTotalCompressedCacheSize; |
| 317 | |
| 318 | PxU64 mContextID; |
| 319 | |
| 320 | friend class PxsCCDContext; |
| 321 | friend class PxsNphaseImplementationContext; |
| 322 | friend class PxgNphaseImplementationContext; //FDTODO ideally it shouldn't be here.. |
| 323 | }; |
| 324 | |
| 325 | |
| 326 | PX_FORCE_INLINE void PxsContext::clearManagerTouchEvents() |
| 327 | { |
| 328 | mContactManagerTouchEvent.clear(); |
| 329 | mContactManagerPatchChangeEvent.clear(); |
| 330 | for(PxU32 i = 0; i < PXS_TOUCH_EVENT_COUNT; ++i) |
| 331 | { |
| 332 | mCMTouchEventCount[i] = 0; |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | |
| 337 | } |
| 338 | |
| 339 | #endif |
| 340 | |