| 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 | #include "geometry/PxGeometry.h" |
| 31 | #include "Ps.h" |
| 32 | #include "GuCCDSweepConvexMesh.h" |
| 33 | #include "PsHashMap.h" |
| 34 | #include "PxsIslandSim.h" |
| 35 | |
| 36 | #ifndef PXS_CCD_H |
| 37 | #define PXS_CCD_H |
| 38 | |
| 39 | #define CCD_DEBUG_PRINTS 0 |
| 40 | #define CCD_POST_DEPENETRATE_DIST 0.001f |
| 41 | #define CCD_ROTATION_LOCKING 0 |
| 42 | #define CCD_MIN_TIME_LEFT 0.01f |
| 43 | #define CCD_ANGULAR_IMPULSE 0 |
| 44 | |
| 45 | #define DEBUG_RENDER_CCD 0 |
| 46 | |
| 47 | #if CCD_DEBUG_PRINTS |
| 48 | namespace physx { |
| 49 | extern void printCCDDebug(const char* msg, const PxsRigidBody* atom0, PxGeometryType::Enum g0, bool printPtr = true); |
| 50 | extern void printShape(PxsRigidBody* atom0, PxGeometryType::Enum g0, const char* annotation, PxReal dt, PxU32 pass, bool printPtr = true); |
| 51 | } |
| 52 | #define PRINTCCDSHAPE(x) printShape x |
| 53 | #define PRINTCCDDEBUG(x) printCCDDebug x |
| 54 | #else |
| 55 | #define PRINTCCDSHAPE(x) |
| 56 | #define PRINTCCDDEBUG(x) |
| 57 | #endif |
| 58 | |
| 59 | namespace physx |
| 60 | { |
| 61 | |
| 62 | // ------------------------------------------------------------------------------------------------------------ |
| 63 | // a fraction of objects will be CCD active so this is dynamic, not a member of PsxRigidBody |
| 64 | // CCD code builds a temporary array of PxsCCDPair objects (allocated in blocks) |
| 65 | // this is done to gather scattered data from memory and also to reduce PxsRidigBody permanent memory footprint |
| 66 | // we have to do it every pass since new CMs can become fast moving after each pass (and sometimes cease to be) |
| 67 | // |
| 68 | struct PxsCCDBody; |
| 69 | class PxsRigidBody; |
| 70 | struct PxsShapeCore; |
| 71 | struct PxsRigidCore; |
| 72 | class PxsContactManager; |
| 73 | class PxsContext; |
| 74 | class PxCCDContactModifyCallback; |
| 75 | class PxcNpThreadContext; |
| 76 | |
| 77 | class PxvNphaseImplementationContext; |
| 78 | |
| 79 | namespace Dy |
| 80 | { |
| 81 | class ThresholdStream; |
| 82 | } |
| 83 | |
| 84 | |
| 85 | /** |
| 86 | \brief structure to represent interactions between a given body and another body. |
| 87 | */ |
| 88 | struct PxsCCDOverlap |
| 89 | { |
| 90 | //The body the interaction relates to |
| 91 | PxsCCDBody* mBody; |
| 92 | //The next interaction in the list |
| 93 | PxsCCDOverlap* mNext; |
| 94 | }; |
| 95 | |
| 96 | /** |
| 97 | \brief Temporary CCD representation for a shape. |
| 98 | |
| 99 | Stores data about a shape that may be frequently used in CCD. It also stores update counters per-shape that can be compared with the body's update |
| 100 | counter to determine if the shape needs its transforms re-calculated. This avoids us needing to store a list of shapes in a CCD body. |
| 101 | */ |
| 102 | struct PxsCCDShape : public Gu::CCDShape |
| 103 | { |
| 104 | public: |
| 105 | const PxsShapeCore* mShapeCore; //Shape core (can be shared) |
| 106 | const PxsRigidCore* mRigidCore; //Rigid body core |
| 107 | IG::NodeIndex mNodeIndex; |
| 108 | |
| 109 | /** |
| 110 | \brief Returns the world-space pose for this shape |
| 111 | \param[in] atom The rigid body that this CCD shape is associated with |
| 112 | */ |
| 113 | PxTransform getAbsPose(const PxsRigidBody* atom) const; |
| 114 | /** |
| 115 | \brief Returns the world-space previous pose for this shape |
| 116 | \param[in] atom The rigid body that this CCD shape is associated with |
| 117 | */ |
| 118 | PxTransform getLastCCDAbsPose(const PxsRigidBody* atom) const; |
| 119 | }; |
| 120 | |
| 121 | /** |
| 122 | \brief Structure to represent a body in the CCD system. |
| 123 | */ |
| 124 | struct PxsCCDBody |
| 125 | { |
| 126 | Cm::SpatialVector mPreSolverVelocity; |
| 127 | PxU16 mIndex; //The CCD body's index |
| 128 | bool mPassDone; //Whether it has been processed in the current CCD pass |
| 129 | bool mHasAnyPassDone; //Whether this body was influenced by any passes |
| 130 | PxReal mTimeLeft; //CCD time left to elapse (normalized in range 0-1) |
| 131 | PxsRigidBody* mBody; //The rigid body |
| 132 | PxsCCDOverlap* mOverlappingObjects; //A list of overlapping bodies for island update |
| 133 | PxU32 mUpdateCount; //How many times this body has eben updated in the CCD. This is correlated with CCD shapes' update counts. |
| 134 | PxU32 mNbInteractionsThisPass; //How many interactions this pass |
| 135 | |
| 136 | |
| 137 | |
| 138 | /** |
| 139 | \brief Returns the CCD body's index. |
| 140 | \return The CCD body's index. |
| 141 | */ |
| 142 | PX_FORCE_INLINE PxU32 getIndex() const { return mIndex; } |
| 143 | |
| 144 | /** |
| 145 | \brief Tests whether this body has already registered an overlap with a given body. |
| 146 | \param[in] body The body to test against. |
| 147 | \return Whether this body has already registered an overlap with a given body. |
| 148 | */ |
| 149 | bool overlaps(PxsCCDBody* body) const |
| 150 | { |
| 151 | PxsCCDOverlap* overlaps = mOverlappingObjects; |
| 152 | |
| 153 | while(overlaps) |
| 154 | { |
| 155 | if(overlaps->mBody == body) |
| 156 | return true; |
| 157 | overlaps = overlaps->mNext; |
| 158 | } |
| 159 | return false; |
| 160 | } |
| 161 | |
| 162 | /** |
| 163 | \brief Registers an overlap with a given body |
| 164 | \param[in] overlap The CCD overlap to register. |
| 165 | */ |
| 166 | void addOverlap(PxsCCDOverlap* overlap) |
| 167 | { |
| 168 | overlap->mNext = mOverlappingObjects; |
| 169 | mOverlappingObjects = overlap; |
| 170 | } |
| 171 | |
| 172 | }; |
| 173 | |
| 174 | /** |
| 175 | \brief a container class used in the CCD that minimizes frequency of hitting the allocator. |
| 176 | |
| 177 | This class stores a set of blocks of memory. It is effectively an array that resizes more efficiently because it doesn't need to |
| 178 | reallocate an entire buffer and copy data. |
| 179 | */ |
| 180 | template<typename T, int BLOCK_SIZE> |
| 181 | struct PxsCCDBlockArray |
| 182 | { |
| 183 | /** |
| 184 | \brief A block of data |
| 185 | */ |
| 186 | struct Block : Ps::UserAllocated { T items[BLOCK_SIZE]; }; |
| 187 | /** |
| 188 | \brief A header for a block of data. |
| 189 | */ |
| 190 | struct BlockInfo |
| 191 | { |
| 192 | Block* block; |
| 193 | PxU32 count; // number of elements in this block |
| 194 | BlockInfo(Block* aBlock, PxU32 aCount) : block(aBlock), count(aCount) {} |
| 195 | }; |
| 196 | /* |
| 197 | \brief An array of block headers |
| 198 | */ |
| 199 | Ps::Array<BlockInfo> blocks; |
| 200 | /** |
| 201 | \brief The current block. |
| 202 | */ |
| 203 | PxU32 currentBlock; |
| 204 | |
| 205 | /** |
| 206 | \brief Constructor |
| 207 | */ |
| 208 | PxsCCDBlockArray() : currentBlock(0) |
| 209 | { |
| 210 | blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); |
| 211 | } |
| 212 | |
| 213 | /** |
| 214 | \brief Destructor |
| 215 | */ |
| 216 | ~PxsCCDBlockArray() |
| 217 | { |
| 218 | for (PxU32 i = 0; i < blocks.size(); i++) |
| 219 | { |
| 220 | PX_DELETE(blocks[i].block); |
| 221 | } |
| 222 | currentBlock = 0; |
| 223 | } |
| 224 | |
| 225 | /** |
| 226 | \brief Clears this block array. |
| 227 | \note This clear function also deletes all additional blocks |
| 228 | */ |
| 229 | void clear() |
| 230 | { |
| 231 | for (PxU32 i = 0; i < blocks.size(); i++) |
| 232 | { |
| 233 | PX_DELETE(blocks[i].block); |
| 234 | } |
| 235 | blocks.clear(); |
| 236 | blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); // at least one block is expected to always be present in the array |
| 237 | currentBlock = 0; |
| 238 | } |
| 239 | |
| 240 | /** |
| 241 | \brief Clears this block array but does not release the memory. |
| 242 | */ |
| 243 | void clear_NoDelete() |
| 244 | { |
| 245 | currentBlock = 0; |
| 246 | blocks[0].count = 0; |
| 247 | } |
| 248 | |
| 249 | /** |
| 250 | \brief Push a new element onto the back of the block array |
| 251 | \return The new element |
| 252 | */ |
| 253 | T& pushBack() |
| 254 | { |
| 255 | PxU32 numBlocks = blocks.size(); |
| 256 | if (blocks[currentBlock].count == BLOCK_SIZE) |
| 257 | { |
| 258 | if((currentBlock + 1) == numBlocks) |
| 259 | { |
| 260 | blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); |
| 261 | numBlocks ++; |
| 262 | } |
| 263 | currentBlock++; |
| 264 | blocks[currentBlock].count = 0; |
| 265 | } |
| 266 | const PxU32 count = blocks[currentBlock].count ++; |
| 267 | |
| 268 | return blocks[currentBlock].block->items[count]; |
| 269 | } |
| 270 | |
| 271 | /** |
| 272 | \brief Pushes a new element onto the back of this array, intitializing it to match the data |
| 273 | \param data The data to initialize the new element to |
| 274 | \return The new element |
| 275 | */ |
| 276 | T& pushBack(T& data) |
| 277 | { |
| 278 | PxU32 numBlocks = blocks.size(); |
| 279 | if (blocks[currentBlock].count == BLOCK_SIZE) |
| 280 | { |
| 281 | if((currentBlock + 1) == numBlocks) |
| 282 | { |
| 283 | blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); |
| 284 | numBlocks ++; |
| 285 | } |
| 286 | currentBlock++; |
| 287 | blocks[currentBlock].count = 0; |
| 288 | } |
| 289 | const PxU32 count = blocks[currentBlock].count ++; |
| 290 | blocks[currentBlock].block->items[count] = data; |
| 291 | return blocks[currentBlock].block->items[count]; |
| 292 | } |
| 293 | |
| 294 | /** |
| 295 | \brief Pops the last element from the list. |
| 296 | */ |
| 297 | void popBack() |
| 298 | { |
| 299 | PX_ASSERT(blocks[currentBlock].count > 0); |
| 300 | if (blocks[currentBlock].count > 1) |
| 301 | blocks[currentBlock].count --; |
| 302 | else |
| 303 | { |
| 304 | PX_DELETE(blocks[currentBlock].block); |
| 305 | blocks.popBack(); |
| 306 | currentBlock--; |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | \brief Returns the current size of the array. |
| 312 | \return The current size of the array. |
| 313 | */ |
| 314 | PxU32 size() const |
| 315 | { |
| 316 | return (currentBlock)*BLOCK_SIZE + blocks[currentBlock].count; |
| 317 | } |
| 318 | |
| 319 | /** |
| 320 | \brief Returns the element at a given index in the array |
| 321 | \param[in] index The index of the element in the array |
| 322 | \return The element at a given index in the array. |
| 323 | */ |
| 324 | T& operator[] (PxU32 index) const |
| 325 | { |
| 326 | PX_ASSERT(index/BLOCK_SIZE < blocks.size()); |
| 327 | PX_ASSERT(index%BLOCK_SIZE < blocks[index/BLOCK_SIZE].count); |
| 328 | return blocks[index/BLOCK_SIZE].block->items[index%BLOCK_SIZE]; |
| 329 | } |
| 330 | }; |
| 331 | |
| 332 | /** |
| 333 | \brief A structure to represent a potential CCD interaction between a pair of shapes |
| 334 | */ |
| 335 | struct PxsCCDPair |
| 336 | { |
| 337 | /** |
| 338 | \brief Defines whether this is an estimated TOI or an accurate TOI. |
| 339 | |
| 340 | We store pairs in a priority queue based on the TOIs. We use cheap estimates to cull away work and lazily evaluate TOIs. This means that an element in the |
| 341 | priority queue may either be an estimate or a precise result. |
| 342 | */ |
| 343 | enum E_TOIType |
| 344 | { |
| 345 | eEstimate, |
| 346 | ePrecise |
| 347 | }; |
| 348 | PxsRigidBody* mBa0; // Body A. Can be NULL for statics |
| 349 | PxsRigidBody* mBa1; // Body B. Can be NULL for statics |
| 350 | PxsCCDShape* mCCDShape0; // Shape A |
| 351 | PxsCCDShape* mCCDShape1; // Shape B |
| 352 | PxVec3 mMinToiNormal; // The contact normal. Only valid for precise results. On the surface of body/shape A |
| 353 | PxReal mMinToi; // Min TOI. Valid for both precise and estimated results but estimates may be too early (i.e. conservative). |
| 354 | PxReal mPenetrationPostStep; // Valid only for precise sweeps. Only used for initial intersections (i.e. at TOI = 0). |
| 355 | PxVec3 mMinToiPoint; // The contact point. Only valid for precise sweep results. |
| 356 | PxReal mPenetration; // The penetration. Only valid for precise sweep results. |
| 357 | PxsContactManager* mCm; // The contact manager. |
| 358 | PxU32 mIslandId; // The index of the island this pair is in |
| 359 | PxGeometryType::Enum mG0, mG1; // The geometry types for shapes 0 and 1 |
| 360 | bool mIsEarliestToiHit; // Indicates this was the earliest hit for one of the bodies in the pair |
| 361 | bool mIsModifiable; // Indicates whether this contact is modifiable |
| 362 | PxU32 mFaceIndex; // The face index. Only valid for precise sweeps involving meshes or heightfields. |
| 363 | PxU16 mMaterialIndex0; // The material index for shape 0 |
| 364 | PxU16 mMaterialIndex1; // The material index for shape 1 |
| 365 | PxReal mDynamicFriction; // The dynamic friction coefficient |
| 366 | PxReal mStaticFriction; // The static friction coefficient |
| 367 | PxReal mRestitution; // The restitution coefficient |
| 368 | PxU32 mEstimatePass; // The current estimation pass. Used after a sweep hit was found to determine if the pair needs re-estimating. |
| 369 | PxReal mAppliedForce; // The applied force for this pair. Only valid if the pair has been responded to. |
| 370 | PxReal mMaxImpulse; // The maximum impulse to be applied |
| 371 | |
| 372 | E_TOIType mToiType; // The TOI type (estimate, precise). |
| 373 | bool mHasFriction; // Whether we want to simulate CCD friction for this pair |
| 374 | |
| 375 | /** |
| 376 | \brief Perform a precise sweep for this pair |
| 377 | \param[in] threadContext The per-thread context |
| 378 | \param[in] dt The time-step |
| 379 | \param[in] pass The current CCD pass |
| 380 | \return The normalized TOI. <=1.0 indicates a hit. Otherwise PX_MAX_REAL. |
| 381 | */ |
| 382 | PxReal sweepFindToi(PxcNpThreadContext& threadContext, PxReal dt, PxU32 pass, PxReal ccdThreshold); |
| 383 | /** |
| 384 | \brief Performs a sweep estimation for this pair |
| 385 | \return The normalized TOI. <= 1.0 indicates a potential hit, otherwise PX_MAX_REAL. |
| 386 | */ |
| 387 | PxReal sweepEstimateToi(PxReal ccdThreshold); |
| 388 | /** |
| 389 | \brief Advances this pair to the TOI |
| 390 | \param[in] dt The time-step |
| 391 | \param[in] clipTrajectoryToToi Indicates whether we clip the body's trajectory to the end pose. Only done in the final pass |
| 392 | \return Whether the advance was successful. An advance will be unsuccessful if body bodies were already updated. |
| 393 | */ |
| 394 | bool sweepAdvanceToToi(PxReal dt, bool clipTrajectoryToToi); |
| 395 | /** |
| 396 | \brief Updates the transforms of the shapes involved in this pair. |
| 397 | */ |
| 398 | void updateShapes(); |
| 399 | |
| 400 | }; |
| 401 | |
| 402 | /** |
| 403 | \brief Block array of CCD bodies |
| 404 | */ |
| 405 | typedef PxsCCDBlockArray<PxsCCDBody, 128> PxsCCDBodyArray; |
| 406 | /** |
| 407 | \brief Block array of CCD pairs |
| 408 | */ |
| 409 | typedef PxsCCDBlockArray<PxsCCDPair, 128> PxsCCDPairArray; |
| 410 | /** |
| 411 | \brief Block array of CCD overlaps |
| 412 | */ |
| 413 | typedef PxsCCDBlockArray<PxsCCDOverlap, 128> PxsCCDOverlapArray; |
| 414 | /** |
| 415 | \brief Block array of CCD shapes |
| 416 | */ |
| 417 | typedef PxsCCDBlockArray<PxsCCDShape, 128> PxsCCDShapeArray; |
| 418 | |
| 419 | /** |
| 420 | \brief Pair structure to be able to look-up a rigid body-shape pair in a map |
| 421 | */ |
| 422 | typedef Ps::Pair<const PxsRigidCore*, const PxsShapeCore*> PxsRigidShapePair; |
| 423 | |
| 424 | |
| 425 | /** |
| 426 | \brief CCD context object. |
| 427 | */ |
| 428 | class PxsCCDContext |
| 429 | { |
| 430 | public: |
| 431 | |
| 432 | /** |
| 433 | \brief Creates this PxsCCDContext |
| 434 | */ |
| 435 | static PxsCCDContext* create(PxsContext* context, Dy::ThresholdStream& dynamicsContext, PxvNphaseImplementationContext& nPhaseContext, |
| 436 | PxReal ccdThreshold); |
| 437 | |
| 438 | /** |
| 439 | \brief Destroys this PxsCCDContext |
| 440 | */ |
| 441 | void destroy(); |
| 442 | |
| 443 | /** |
| 444 | \brief Returns the CCD contact modification callback |
| 445 | \return The CCD contact modification callback |
| 446 | */ |
| 447 | PX_FORCE_INLINE PxCCDContactModifyCallback* getCCDContactModifyCallback() const { return mCCDContactModifyCallback; } |
| 448 | /** |
| 449 | \brief Sets the CCD contact modification callback |
| 450 | \param[in] c The CCD contact modification callback |
| 451 | */ |
| 452 | PX_FORCE_INLINE void setCCDContactModifyCallback(PxCCDContactModifyCallback* c) { mCCDContactModifyCallback = c; } |
| 453 | /** |
| 454 | \brief Returns the maximum number of CCD passes |
| 455 | \return The maximum number of CCD passes |
| 456 | */ |
| 457 | PX_FORCE_INLINE PxU32 getCCDMaxPasses() const { return mCCDMaxPasses; } |
| 458 | /** |
| 459 | \brief Sets the maximum number of CCD passes |
| 460 | \param[in] ccdMaxPasses The maximum number of CCD passes |
| 461 | */ |
| 462 | PX_FORCE_INLINE void setCCDMaxPasses(PxU32 ccdMaxPasses) { mCCDMaxPasses = ccdMaxPasses; } |
| 463 | /** |
| 464 | \brief Returns the current CCD pass |
| 465 | \return The current CCD pass |
| 466 | */ |
| 467 | PX_FORCE_INLINE PxU32 getCurrentCCDPass() const { return miCCDPass; } |
| 468 | /** |
| 469 | \brief Returns The number of swept hits reported |
| 470 | \return The number of swept hits reported |
| 471 | */ |
| 472 | PX_FORCE_INLINE PxI32 getNumSweepHits() const { return mSweepTotalHits; } |
| 473 | /** |
| 474 | \brief Returns The number of updated bodies |
| 475 | \return The number of updated bodies in this CCD pass |
| 476 | */ |
| 477 | PX_FORCE_INLINE PxU32 getNumUpdatedBodies() const { return mUpdatedCCDBodies.size(); } |
| 478 | /** |
| 479 | \brief Returns The update bodies array |
| 480 | \return The updated bodies array from this CCD pass |
| 481 | */ |
| 482 | PX_FORCE_INLINE PxsRigidBody*const* getUpdatedBodies() const { return mUpdatedCCDBodies.begin(); } |
| 483 | |
| 484 | /** |
| 485 | \brief Returns Clears the updated bodies array |
| 486 | */ |
| 487 | PX_FORCE_INLINE void clearUpdatedBodies() { mUpdatedCCDBodies.forceSize_Unsafe(size: 0); } |
| 488 | |
| 489 | PX_FORCE_INLINE PxReal getCCDThreshold() const { return mCCDThreshold;} |
| 490 | |
| 491 | /** |
| 492 | \brief Runs the CCD contact modification. |
| 493 | \param[in] contacts The list of modifiable contacts |
| 494 | \param[in] contactCount The number of contacts |
| 495 | \param[in] shapeCore0 The first shape core |
| 496 | \param[in] shapeCore1 The second shape core |
| 497 | \param[in] rigidCore0 The first rigid core |
| 498 | \param[in] rigidCore1 The second rigid core |
| 499 | \param[in] rigid0 The first rigid body |
| 500 | \param[in] rigid1 The second rigid body |
| 501 | */ |
| 502 | void runCCDModifiableContact(PxModifiableContact* PX_RESTRICT contacts, PxU32 contactCount, const PxsShapeCore* PX_RESTRICT shapeCore0, |
| 503 | const PxsShapeCore* PX_RESTRICT shapeCore1, const PxsRigidCore* PX_RESTRICT rigidCore0, const PxsRigidCore* PX_RESTRICT rigidCore1, |
| 504 | const PxsRigidBody* PX_RESTRICT rigid0, const PxsRigidBody* PX_RESTRICT rigid1); |
| 505 | |
| 506 | /** |
| 507 | \brief Performs a single CCD update |
| 508 | This occurs after broad phase and is responsible for creating islands, finding the TOI of collisions, filtering contacts, issuing modification callbacks and responding to |
| 509 | collisions. At the end of this phase all bodies will have stepper to their first TOI if they were involved in a CCD collision this frame. |
| 510 | \param[in] dt The timestep to simulate |
| 511 | \param[in] continuation The continuation task |
| 512 | \param[in] islandSim The island manager |
| 513 | \param[in] disableResweep If this is true, we perform a reduced-fidelity CCD approach |
| 514 | */ |
| 515 | void updateCCD(PxReal dt, PxBaseTask* continuation, IG::IslandSim& islandSim, bool disableResweep, PxI32 numFastMovingShapes); |
| 516 | |
| 517 | /** |
| 518 | \brief Signals the beginning of a CCD multi-pass update |
| 519 | */ |
| 520 | void updateCCDBegin(); |
| 521 | |
| 522 | /** |
| 523 | \brief Resets the CCD contact state in any contact managers that previously had a reported CCD touch. This must be called if CCD update is bypassed for a frame |
| 524 | */ |
| 525 | void resetContactManagers(); |
| 526 | |
| 527 | |
| 528 | |
| 529 | |
| 530 | protected: |
| 531 | |
| 532 | /** |
| 533 | \brief Constructor for PxsCCDContext |
| 534 | \param[in] context The PxsContext that is associated with this PxsCCDContext. |
| 535 | */ |
| 536 | PxsCCDContext(PxsContext* context, Dy::ThresholdStream& thresholdStream, PxvNphaseImplementationContext& nPhaseContext, |
| 537 | PxReal ccdThreshold); |
| 538 | /** |
| 539 | \brief Destructor for PxsCCDContext |
| 540 | */ |
| 541 | ~PxsCCDContext(); |
| 542 | |
| 543 | private: |
| 544 | |
| 545 | |
| 546 | /** |
| 547 | \brief Verifies the consistency of the CCD context at the beginning |
| 548 | */ |
| 549 | void verifyCCDBegin(); |
| 550 | |
| 551 | /** |
| 552 | \brief Cleans up after the CCD update has completed |
| 553 | */ |
| 554 | void updateCCDEnd(); |
| 555 | |
| 556 | /** |
| 557 | \brief Spawns the update island tasks after the initial sweep estimates have been performed |
| 558 | \param[in] continuation The continuation task |
| 559 | */ |
| 560 | void postCCDSweep(PxBaseTask* continuation); |
| 561 | /** |
| 562 | \brief Creates contact buffers for CCD contacts. These will be sent to the user in the contact notification. |
| 563 | \param[in] continuation The continuation task |
| 564 | */ |
| 565 | void postCCDAdvance(PxBaseTask* continuation); |
| 566 | /** |
| 567 | \brief The final phase of the CCD task chain. Cleans up after the parallel update/postCCDAdvance stages. |
| 568 | \param[in] continuation The continuation task |
| 569 | */ |
| 570 | void postCCDDepenetrate(PxBaseTask* continuation); |
| 571 | |
| 572 | typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDSweep> PostCCDSweepTask; |
| 573 | typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDAdvance> PostCCDAdvanceTask; |
| 574 | typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDDepenetrate> PostCCDDepenetrateTask; |
| 575 | |
| 576 | PostCCDSweepTask mPostCCDSweepTask; |
| 577 | PostCCDAdvanceTask mPostCCDAdvanceTask; |
| 578 | PostCCDDepenetrateTask mPostCCDDepenetrateTask; |
| 579 | |
| 580 | PxCCDContactModifyCallback* mCCDContactModifyCallback; |
| 581 | |
| 582 | // CCD global data |
| 583 | bool mDisableCCDResweep; |
| 584 | PxU32 miCCDPass; |
| 585 | PxI32 mSweepTotalHits; |
| 586 | |
| 587 | // a fraction of objects will be CCD active so PxsCCDBody is dynamic, not a member of PxsRigidBody |
| 588 | PxsCCDBodyArray mCCDBodies; |
| 589 | PxsCCDOverlapArray mCCDOverlaps; |
| 590 | PxsCCDShapeArray mCCDShapes; |
| 591 | Ps::Array<PxsCCDBody*> mIslandBodies; |
| 592 | Ps::Array<PxU16> mIslandSizes; |
| 593 | Ps::Array<PxsRigidBody*> mUpdatedCCDBodies; |
| 594 | Ps::HashMap<PxsRigidShapePair, PxsCCDShape*> mMap; |
| 595 | |
| 596 | // temporary array updated during CCD update |
| 597 | //Array<PxsCCDPair> mCCDPairs; |
| 598 | PxsCCDPairArray mCCDPairs; |
| 599 | Ps::Array<PxsCCDPair*> mCCDPtrPairs; |
| 600 | // number of pairs per island |
| 601 | Ps::Array<PxU32> mCCDIslandHistogram; |
| 602 | // thread context valid during CCD update |
| 603 | PxcNpThreadContext* mCCDThreadContext; |
| 604 | // number of pairs to process per thread |
| 605 | PxU32 mCCDPairsPerBatch; |
| 606 | PxU32 mCCDMaxPasses; |
| 607 | |
| 608 | PxsContext* mContext; |
| 609 | Dy::ThresholdStream& mThresholdStream; |
| 610 | |
| 611 | PxvNphaseImplementationContext& mNphaseContext; |
| 612 | |
| 613 | Ps::Mutex mMutex; |
| 614 | |
| 615 | PxReal mCCDThreshold; |
| 616 | |
| 617 | private: |
| 618 | |
| 619 | PX_NOCOPY(PxsCCDContext) |
| 620 | }; |
| 621 | |
| 622 | |
| 623 | } |
| 624 | |
| 625 | |
| 626 | |
| 627 | #endif |
| 628 | |
| 629 | |