This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,51 @@
//
// 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-2021 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 PXS_BODYSIM_H
#define PXS_BODYSIM_H
#include "PxsRigidBody.h"
namespace physx
{
struct PxsBodySim
{
public:
PxsBodySim() : mRigidBody(NULL)/*, mBodySimIndex(0xffffffff), mUpdated(0)*/
{
}
PxsRigidBody* mRigidBody; //4 or 8
//PxU32 mUpdated; //12 or 16
};
}//physx
#endif

View File

@ -0,0 +1,628 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "geometry/PxGeometry.h"
#include "Ps.h"
#include "GuCCDSweepConvexMesh.h"
#include "PsHashMap.h"
#include "PxsIslandSim.h"
#ifndef PXS_CCD_H
#define PXS_CCD_H
#define CCD_DEBUG_PRINTS 0
#define CCD_POST_DEPENETRATE_DIST 0.001f
#define CCD_ROTATION_LOCKING 0
#define CCD_MIN_TIME_LEFT 0.01f
#define CCD_ANGULAR_IMPULSE 0
#define DEBUG_RENDER_CCD 0
#if CCD_DEBUG_PRINTS
namespace physx {
extern void printCCDDebug(const char* msg, const PxsRigidBody* atom0, PxGeometryType::Enum g0, bool printPtr = true);
extern void printShape(PxsRigidBody* atom0, PxGeometryType::Enum g0, const char* annotation, PxReal dt, PxU32 pass, bool printPtr = true);
}
#define PRINTCCDSHAPE(x) printShape x
#define PRINTCCDDEBUG(x) printCCDDebug x
#else
#define PRINTCCDSHAPE(x)
#define PRINTCCDDEBUG(x)
#endif
namespace physx
{
// ------------------------------------------------------------------------------------------------------------
// a fraction of objects will be CCD active so this is dynamic, not a member of PsxRigidBody
// CCD code builds a temporary array of PxsCCDPair objects (allocated in blocks)
// this is done to gather scattered data from memory and also to reduce PxsRidigBody permanent memory footprint
// we have to do it every pass since new CMs can become fast moving after each pass (and sometimes cease to be)
//
struct PxsCCDBody;
class PxsRigidBody;
struct PxsShapeCore;
struct PxsRigidCore;
class PxsContactManager;
class PxsContext;
class PxCCDContactModifyCallback;
class PxcNpThreadContext;
class PxvNphaseImplementationContext;
namespace Dy
{
class ThresholdStream;
}
/**
\brief structure to represent interactions between a given body and another body.
*/
struct PxsCCDOverlap
{
//The body the interaction relates to
PxsCCDBody* mBody;
//The next interaction in the list
PxsCCDOverlap* mNext;
};
/**
\brief Temporary CCD representation for a shape.
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
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.
*/
struct PxsCCDShape : public Gu::CCDShape
{
public:
const PxsShapeCore* mShapeCore; //Shape core (can be shared)
const PxsRigidCore* mRigidCore; //Rigid body core
IG::NodeIndex mNodeIndex;
/**
\brief Returns the world-space pose for this shape
\param[in] atom The rigid body that this CCD shape is associated with
*/
PxTransform getAbsPose(const PxsRigidBody* atom) const;
/**
\brief Returns the world-space previous pose for this shape
\param[in] atom The rigid body that this CCD shape is associated with
*/
PxTransform getLastCCDAbsPose(const PxsRigidBody* atom) const;
};
/**
\brief Structure to represent a body in the CCD system.
*/
struct PxsCCDBody
{
Cm::SpatialVector mPreSolverVelocity;
PxU16 mIndex; //The CCD body's index
bool mPassDone; //Whether it has been processed in the current CCD pass
bool mHasAnyPassDone; //Whether this body was influenced by any passes
PxReal mTimeLeft; //CCD time left to elapse (normalized in range 0-1)
PxsRigidBody* mBody; //The rigid body
PxsCCDOverlap* mOverlappingObjects; //A list of overlapping bodies for island update
PxU32 mUpdateCount; //How many times this body has eben updated in the CCD. This is correlated with CCD shapes' update counts.
PxU32 mNbInteractionsThisPass; //How many interactions this pass
/**
\brief Returns the CCD body's index.
\return The CCD body's index.
*/
PX_FORCE_INLINE PxU32 getIndex() const { return mIndex; }
/**
\brief Tests whether this body has already registered an overlap with a given body.
\param[in] body The body to test against.
\return Whether this body has already registered an overlap with a given body.
*/
bool overlaps(PxsCCDBody* body) const
{
PxsCCDOverlap* overlaps = mOverlappingObjects;
while(overlaps)
{
if(overlaps->mBody == body)
return true;
overlaps = overlaps->mNext;
}
return false;
}
/**
\brief Registers an overlap with a given body
\param[in] overlap The CCD overlap to register.
*/
void addOverlap(PxsCCDOverlap* overlap)
{
overlap->mNext = mOverlappingObjects;
mOverlappingObjects = overlap;
}
};
/**
\brief a container class used in the CCD that minimizes frequency of hitting the allocator.
This class stores a set of blocks of memory. It is effectively an array that resizes more efficiently because it doesn't need to
reallocate an entire buffer and copy data.
*/
template<typename T, int BLOCK_SIZE>
struct PxsCCDBlockArray
{
/**
\brief A block of data
*/
struct Block : Ps::UserAllocated { T items[BLOCK_SIZE]; };
/**
\brief A header for a block of data.
*/
struct BlockInfo
{
Block* block;
PxU32 count; // number of elements in this block
BlockInfo(Block* aBlock, PxU32 aCount) : block(aBlock), count(aCount) {}
};
/*
\brief An array of block headers
*/
Ps::Array<BlockInfo> blocks;
/**
\brief The current block.
*/
PxU32 currentBlock;
/**
\brief Constructor
*/
PxsCCDBlockArray() : currentBlock(0)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
}
/**
\brief Destructor
*/
~PxsCCDBlockArray()
{
for (PxU32 i = 0; i < blocks.size(); i++)
{
PX_DELETE(blocks[i].block);
}
currentBlock = 0;
}
/**
\brief Clears this block array.
\note This clear function also deletes all additional blocks
*/
void clear()
{
for (PxU32 i = 0; i < blocks.size(); i++)
{
PX_DELETE(blocks[i].block);
}
blocks.clear();
blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); // at least one block is expected to always be present in the array
currentBlock = 0;
}
/**
\brief Clears this block array but does not release the memory.
*/
void clear_NoDelete()
{
currentBlock = 0;
blocks[0].count = 0;
}
/**
\brief Push a new element onto the back of the block array
\return The new element
*/
T& pushBack()
{
PxU32 numBlocks = blocks.size();
if (blocks[currentBlock].count == BLOCK_SIZE)
{
if((currentBlock + 1) == numBlocks)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
numBlocks ++;
}
currentBlock++;
blocks[currentBlock].count = 0;
}
const PxU32 count = blocks[currentBlock].count ++;
return blocks[currentBlock].block->items[count];
}
/**
\brief Pushes a new element onto the back of this array, intitializing it to match the data
\param data The data to initialize the new element to
\return The new element
*/
T& pushBack(T& data)
{
PxU32 numBlocks = blocks.size();
if (blocks[currentBlock].count == BLOCK_SIZE)
{
if((currentBlock + 1) == numBlocks)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
numBlocks ++;
}
currentBlock++;
blocks[currentBlock].count = 0;
}
const PxU32 count = blocks[currentBlock].count ++;
blocks[currentBlock].block->items[count] = data;
return blocks[currentBlock].block->items[count];
}
/**
\brief Pops the last element from the list.
*/
void popBack()
{
PX_ASSERT(blocks[currentBlock].count > 0);
if (blocks[currentBlock].count > 1)
blocks[currentBlock].count --;
else
{
PX_DELETE(blocks[currentBlock].block);
blocks.popBack();
currentBlock--;
}
}
/**
\brief Returns the current size of the array.
\return The current size of the array.
*/
PxU32 size() const
{
return (currentBlock)*BLOCK_SIZE + blocks[currentBlock].count;
}
/**
\brief Returns the element at a given index in the array
\param[in] index The index of the element in the array
\return The element at a given index in the array.
*/
T& operator[] (PxU32 index) const
{
PX_ASSERT(index/BLOCK_SIZE < blocks.size());
PX_ASSERT(index%BLOCK_SIZE < blocks[index/BLOCK_SIZE].count);
return blocks[index/BLOCK_SIZE].block->items[index%BLOCK_SIZE];
}
};
/**
\brief A structure to represent a potential CCD interaction between a pair of shapes
*/
struct PxsCCDPair
{
/**
\brief Defines whether this is an estimated TOI or an accurate TOI.
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
priority queue may either be an estimate or a precise result.
*/
enum E_TOIType
{
eEstimate,
ePrecise
};
PxsRigidBody* mBa0; // Body A. Can be NULL for statics
PxsRigidBody* mBa1; // Body B. Can be NULL for statics
PxsCCDShape* mCCDShape0; // Shape A
PxsCCDShape* mCCDShape1; // Shape B
PxVec3 mMinToiNormal; // The contact normal. Only valid for precise results. On the surface of body/shape A
PxReal mMinToi; // Min TOI. Valid for both precise and estimated results but estimates may be too early (i.e. conservative).
PxReal mPenetrationPostStep; // Valid only for precise sweeps. Only used for initial intersections (i.e. at TOI = 0).
PxVec3 mMinToiPoint; // The contact point. Only valid for precise sweep results.
PxReal mPenetration; // The penetration. Only valid for precise sweep results.
PxsContactManager* mCm; // The contact manager.
PxU32 mIslandId; // The index of the island this pair is in
PxGeometryType::Enum mG0, mG1; // The geometry types for shapes 0 and 1
bool mIsEarliestToiHit; // Indicates this was the earliest hit for one of the bodies in the pair
bool mIsModifiable; // Indicates whether this contact is modifiable
PxU32 mFaceIndex; // The face index. Only valid for precise sweeps involving meshes or heightfields.
PxU16 mMaterialIndex0; // The material index for shape 0
PxU16 mMaterialIndex1; // The material index for shape 1
PxReal mDynamicFriction; // The dynamic friction coefficient
PxReal mStaticFriction; // The static friction coefficient
PxReal mRestitution; // The restitution coefficient
PxU32 mEstimatePass; // The current estimation pass. Used after a sweep hit was found to determine if the pair needs re-estimating.
PxReal mAppliedForce; // The applied force for this pair. Only valid if the pair has been responded to.
PxReal mMaxImpulse; // The maximum impulse to be applied
E_TOIType mToiType; // The TOI type (estimate, precise).
bool mHasFriction; // Whether we want to simulate CCD friction for this pair
/**
\brief Perform a precise sweep for this pair
\param[in] threadContext The per-thread context
\param[in] dt The time-step
\param[in] pass The current CCD pass
\return The normalized TOI. <=1.0 indicates a hit. Otherwise PX_MAX_REAL.
*/
PxReal sweepFindToi(PxcNpThreadContext& threadContext, PxReal dt, PxU32 pass, PxReal ccdThreshold);
/**
\brief Performs a sweep estimation for this pair
\return The normalized TOI. <= 1.0 indicates a potential hit, otherwise PX_MAX_REAL.
*/
PxReal sweepEstimateToi(PxReal ccdThreshold);
/**
\brief Advances this pair to the TOI
\param[in] dt The time-step
\param[in] clipTrajectoryToToi Indicates whether we clip the body's trajectory to the end pose. Only done in the final pass
\return Whether the advance was successful. An advance will be unsuccessful if body bodies were already updated.
*/
bool sweepAdvanceToToi(PxReal dt, bool clipTrajectoryToToi);
/**
\brief Updates the transforms of the shapes involved in this pair.
*/
void updateShapes();
};
/**
\brief Block array of CCD bodies
*/
typedef PxsCCDBlockArray<PxsCCDBody, 128> PxsCCDBodyArray;
/**
\brief Block array of CCD pairs
*/
typedef PxsCCDBlockArray<PxsCCDPair, 128> PxsCCDPairArray;
/**
\brief Block array of CCD overlaps
*/
typedef PxsCCDBlockArray<PxsCCDOverlap, 128> PxsCCDOverlapArray;
/**
\brief Block array of CCD shapes
*/
typedef PxsCCDBlockArray<PxsCCDShape, 128> PxsCCDShapeArray;
/**
\brief Pair structure to be able to look-up a rigid body-shape pair in a map
*/
typedef Ps::Pair<const PxsRigidCore*, const PxsShapeCore*> PxsRigidShapePair;
/**
\brief CCD context object.
*/
class PxsCCDContext
{
public:
/**
\brief Creates this PxsCCDContext
*/
static PxsCCDContext* create(PxsContext* context, Dy::ThresholdStream& dynamicsContext, PxvNphaseImplementationContext& nPhaseContext,
PxReal ccdThreshold);
/**
\brief Destroys this PxsCCDContext
*/
void destroy();
/**
\brief Returns the CCD contact modification callback
\return The CCD contact modification callback
*/
PX_FORCE_INLINE PxCCDContactModifyCallback* getCCDContactModifyCallback() const { return mCCDContactModifyCallback; }
/**
\brief Sets the CCD contact modification callback
\param[in] c The CCD contact modification callback
*/
PX_FORCE_INLINE void setCCDContactModifyCallback(PxCCDContactModifyCallback* c) { mCCDContactModifyCallback = c; }
/**
\brief Returns the maximum number of CCD passes
\return The maximum number of CCD passes
*/
PX_FORCE_INLINE PxU32 getCCDMaxPasses() const { return mCCDMaxPasses; }
/**
\brief Sets the maximum number of CCD passes
\param[in] ccdMaxPasses The maximum number of CCD passes
*/
PX_FORCE_INLINE void setCCDMaxPasses(PxU32 ccdMaxPasses) { mCCDMaxPasses = ccdMaxPasses; }
/**
\brief Returns the current CCD pass
\return The current CCD pass
*/
PX_FORCE_INLINE PxU32 getCurrentCCDPass() const { return miCCDPass; }
/**
\brief Returns The number of swept hits reported
\return The number of swept hits reported
*/
PX_FORCE_INLINE PxI32 getNumSweepHits() const { return mSweepTotalHits; }
/**
\brief Returns The number of updated bodies
\return The number of updated bodies in this CCD pass
*/
PX_FORCE_INLINE PxU32 getNumUpdatedBodies() const { return mUpdatedCCDBodies.size(); }
/**
\brief Returns The update bodies array
\return The updated bodies array from this CCD pass
*/
PX_FORCE_INLINE PxsRigidBody*const* getUpdatedBodies() const { return mUpdatedCCDBodies.begin(); }
/**
\brief Returns Clears the updated bodies array
*/
PX_FORCE_INLINE void clearUpdatedBodies() { mUpdatedCCDBodies.forceSize_Unsafe(0); }
PX_FORCE_INLINE PxReal getCCDThreshold() const { return mCCDThreshold;}
/**
\brief Runs the CCD contact modification.
\param[in] contacts The list of modifiable contacts
\param[in] contactCount The number of contacts
\param[in] shapeCore0 The first shape core
\param[in] shapeCore1 The second shape core
\param[in] rigidCore0 The first rigid core
\param[in] rigidCore1 The second rigid core
\param[in] rigid0 The first rigid body
\param[in] rigid1 The second rigid body
*/
void runCCDModifiableContact(PxModifiableContact* PX_RESTRICT contacts, PxU32 contactCount, const PxsShapeCore* PX_RESTRICT shapeCore0,
const PxsShapeCore* PX_RESTRICT shapeCore1, const PxsRigidCore* PX_RESTRICT rigidCore0, const PxsRigidCore* PX_RESTRICT rigidCore1,
const PxsRigidBody* PX_RESTRICT rigid0, const PxsRigidBody* PX_RESTRICT rigid1);
/**
\brief Performs a single CCD update
This occurs after broad phase and is responsible for creating islands, finding the TOI of collisions, filtering contacts, issuing modification callbacks and responding to
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.
\param[in] dt The timestep to simulate
\param[in] continuation The continuation task
\param[in] islandSim The island manager
\param[in] disableResweep If this is true, we perform a reduced-fidelity CCD approach
*/
void updateCCD(PxReal dt, PxBaseTask* continuation, IG::IslandSim& islandSim, bool disableResweep, PxI32 numFastMovingShapes);
/**
\brief Signals the beginning of a CCD multi-pass update
*/
void updateCCDBegin();
/**
\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
*/
void resetContactManagers();
protected:
/**
\brief Constructor for PxsCCDContext
\param[in] context The PxsContext that is associated with this PxsCCDContext.
*/
PxsCCDContext(PxsContext* context, Dy::ThresholdStream& thresholdStream, PxvNphaseImplementationContext& nPhaseContext,
PxReal ccdThreshold);
/**
\brief Destructor for PxsCCDContext
*/
~PxsCCDContext();
private:
/**
\brief Verifies the consistency of the CCD context at the beginning
*/
void verifyCCDBegin();
/**
\brief Cleans up after the CCD update has completed
*/
void updateCCDEnd();
/**
\brief Spawns the update island tasks after the initial sweep estimates have been performed
\param[in] continuation The continuation task
*/
void postCCDSweep(PxBaseTask* continuation);
/**
\brief Creates contact buffers for CCD contacts. These will be sent to the user in the contact notification.
\param[in] continuation The continuation task
*/
void postCCDAdvance(PxBaseTask* continuation);
/**
\brief The final phase of the CCD task chain. Cleans up after the parallel update/postCCDAdvance stages.
\param[in] continuation The continuation task
*/
void postCCDDepenetrate(PxBaseTask* continuation);
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDSweep> PostCCDSweepTask;
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDAdvance> PostCCDAdvanceTask;
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDDepenetrate> PostCCDDepenetrateTask;
PostCCDSweepTask mPostCCDSweepTask;
PostCCDAdvanceTask mPostCCDAdvanceTask;
PostCCDDepenetrateTask mPostCCDDepenetrateTask;
PxCCDContactModifyCallback* mCCDContactModifyCallback;
// CCD global data
bool mDisableCCDResweep;
PxU32 miCCDPass;
PxI32 mSweepTotalHits;
// a fraction of objects will be CCD active so PxsCCDBody is dynamic, not a member of PxsRigidBody
PxsCCDBodyArray mCCDBodies;
PxsCCDOverlapArray mCCDOverlaps;
PxsCCDShapeArray mCCDShapes;
Ps::Array<PxsCCDBody*> mIslandBodies;
Ps::Array<PxU16> mIslandSizes;
Ps::Array<PxsRigidBody*> mUpdatedCCDBodies;
Ps::HashMap<PxsRigidShapePair, PxsCCDShape*> mMap;
// temporary array updated during CCD update
//Array<PxsCCDPair> mCCDPairs;
PxsCCDPairArray mCCDPairs;
Ps::Array<PxsCCDPair*> mCCDPtrPairs;
// number of pairs per island
Ps::Array<PxU32> mCCDIslandHistogram;
// thread context valid during CCD update
PxcNpThreadContext* mCCDThreadContext;
// number of pairs to process per thread
PxU32 mCCDPairsPerBatch;
PxU32 mCCDMaxPasses;
PxsContext* mContext;
Dy::ThresholdStream& mThresholdStream;
PxvNphaseImplementationContext& mNphaseContext;
Ps::Mutex mMutex;
PxReal mCCDThreshold;
private:
PX_NOCOPY(PxsCCDContext)
};
}
#endif

View File

@ -0,0 +1,178 @@
//
// 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-2021 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 PXS_CONTACTMANAGER_H
#define PXS_CONTACTMANAGER_H
#include "PxvConfig.h"
#include "PxcNpWorkUnit.h"
namespace physx
{
class PxsContext;
class PxsRigidBody;
struct PxsCCDBody;
class PxsMaterialManager;
struct PxsCCDShape;
namespace Dy
{
class DynamicsContext;
}
namespace Sc
{
class ShapeInteraction;
}
enum PxsPairVisColor
{
eVIS_COLOR_SWEPTINTEGRATE_OFF = 0x000000,
eVIS_COLOR_SWEPTINTEGRATE_SLOW = 0x404040,
eVIS_COLOR_SWEPTINTEGRATE_CLEAR = 0x007f00,
eVIS_COLOR_SWEPTINTEGRATE_IMPACT = 0x1680ff,
eVIS_COLOR_SWEPTINTEGRATE_FAIL = 0x0000ff
};
/**
\brief Additional header structure for CCD contact data stream.
*/
struct PxsCCDContactHeader
{
/**
\brief Stream for next collision. The same pair can collide multiple times during multiple CCD passes.
*/
PxsCCDContactHeader* nextStream; //4 //8
/**
\brief Size (in bytes) of the CCD contact stream (not including force buffer)
*/
PxU16 contactStreamSize; //6 //10
/**
\brief Defines whether the stream is from a previous pass.
It could happen that the stream can not get allocated because we run out of memory. In that case the current event should not use the stream
from an event of the previous pass.
*/
PxU16 isFromPreviousPass; //8 //12
PxU8 pad[12 - sizeof(PxsCCDContactHeader*)]; //16
};
PX_COMPILE_TIME_ASSERT((sizeof(PxsCCDContactHeader) & 0xF) == 0);
class PxsContactManager
{
public:
PxsContactManager(PxsContext* context, PxU32 index);
~PxsContactManager();
PX_FORCE_INLINE void setDisableStrongFriction(PxU32 d) { (!d) ? mNpUnit.flags &= ~PxcNpWorkUnitFlag::eDISABLE_STRONG_FRICTION
: mNpUnit.flags |= PxcNpWorkUnitFlag::eDISABLE_STRONG_FRICTION; }
PX_FORCE_INLINE PxReal getRestDistance() const { return mNpUnit.restDistance; }
PX_FORCE_INLINE void setRestDistance(PxReal v) { mNpUnit.restDistance = v; }
void destroy();
PX_FORCE_INLINE PxU8 getDominance0() const { return mNpUnit.dominance0; }
PX_FORCE_INLINE void setDominance0(PxU8 v) { mNpUnit.dominance0 = v; }
PX_FORCE_INLINE PxU8 getDominance1() const { return mNpUnit.dominance1; }
PX_FORCE_INLINE void setDominance1(PxU8 v) { mNpUnit.dominance1 = v; }
PX_FORCE_INLINE PxU16 getTouchStatus() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eHAS_TOUCH); }
PX_FORCE_INLINE PxU16 touchStatusKnown() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eTOUCH_KNOWN); }
PX_FORCE_INLINE PxI32 getTouchIdx() const { return (mNpUnit.statusFlags& PxcNpWorkUnitStatusFlag::eHAS_TOUCH) ? 1 : (mNpUnit.statusFlags& PxcNpWorkUnitStatusFlag::eHAS_NO_TOUCH ? -1 : 0); }
PX_FORCE_INLINE PxU32 getIndex() const { return mNpUnit.index; }
PX_FORCE_INLINE PxU16 getHasCCDRetouch() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH); }
PX_FORCE_INLINE void clearCCDRetouch() { mNpUnit.statusFlags &= ~PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH; }
PX_FORCE_INLINE void raiseCCDRetouch() { mNpUnit.statusFlags |= PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH; }
// flags stuff - needs to be refactored
PX_FORCE_INLINE Ps::IntBool isChangeable() const { return Ps::IntBool(mFlags & PXS_CM_CHANGEABLE); }
PX_FORCE_INLINE Ps::IntBool getCCD() const { return Ps::IntBool((mFlags & PXS_CM_CCD_LINEAR) && (mNpUnit.flags & PxcNpWorkUnitFlag::eDETECT_CCD_CONTACTS)); }
PX_FORCE_INLINE Ps::IntBool getHadCCDContact() const { return Ps::IntBool(mFlags & PXS_CM_CCD_CONTACT); }
PX_FORCE_INLINE void setHadCCDContact() { mFlags |= PXS_CM_CCD_CONTACT; }
void setCCD(bool enable);
PX_FORCE_INLINE void clearCCDContactInfo() { mFlags &= ~PXS_CM_CCD_CONTACT; mNpUnit.ccdContacts = NULL; }
PX_FORCE_INLINE PxcNpWorkUnit& getWorkUnit() { return mNpUnit; }
PX_FORCE_INLINE const PxcNpWorkUnit& getWorkUnit() const { return mNpUnit; }
PX_FORCE_INLINE void* getUserData() const { return mShapeInteraction; }
// Setup solver-constraints
void resetCachedState();
void resetFrictionCachedState();
Sc::ShapeInteraction* getShapeInteraction() const { return mShapeInteraction; }
private:
//KS - moving this up - we want to get at flags
PxsRigidBody* mRigidBody0; //4 //8
PxsRigidBody* mRigidBody1; //8 //16
PxU32 mFlags; //20 //36
Sc::ShapeInteraction* mShapeInteraction; //16 //32
friend class PxsContext;
// everything required for narrow phase to run
PxcNpWorkUnit mNpUnit;
enum
{
PXS_CM_CHANGEABLE = (1<<0),
PXS_CM_CCD_LINEAR = (1<<1),
PXS_CM_CCD_CONTACT = (1 << 2)
};
friend class Dy::DynamicsContext;
friend struct PxsCCDPair;
friend class PxsIslandManager;
friend class PxsCCDContext;
friend class Sc::ShapeInteraction;
};
}
#endif

View File

@ -0,0 +1,95 @@
//
// 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-2021 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 PXS_CONTACT_MANAGER_STATE_H
#define PXS_CONTACT_MANAGER_STATE_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
struct PxsShapeCore;
/**
There is an implicit 1:1 mapping between PxgContactManagerInput and PxsContactManagerOutput. The structures are split because PxgNpContactManagerInput contains constant
data that is produced by the CPU code and PxgNpContactManagerOutput contains per-frame contact information produced by the NP.
There is also a 1:1 mapping between the PxgNpContactManager and PxsContactManager. This mapping is handled within the PxgNPhaseCore.
The previous contact states are implicitly cached in PxsContactManager and will be propagated to the solver. Friction correlation is also done implicitly using cached
information in PxsContactManager.
The NP will produce a list of pairs that found/lost patches for the solver along with updating the PxgNpContactManagerOutput for all pairs.
*/
struct PxsContactManagerStatusFlag
{
enum Enum
{
eHAS_NO_TOUCH = (1 << 0),
eHAS_TOUCH = (1 << 1),
//eHAS_SOLVER_CONSTRAINTS = (1 << 2),
eREQUEST_CONSTRAINTS = (1 << 3),
eHAS_CCD_RETOUCH = (1 << 4), // Marks pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already
// but we can not tell whether they lost contact in a pass before. We send them as pure eNOTIFY_TOUCH_CCD events to the
// contact report callback if requested.
eDIRTY_MANAGER = (1 << 5),
eTOUCH_KNOWN = eHAS_NO_TOUCH | eHAS_TOUCH // The touch status is known (if narrowphase never ran for a pair then no flag will be set)
};
};
struct PX_ALIGN_PREFIX(16) PxsContactManagerOutput
{
PxU8* contactPatches; //Start index/ptr for contact patches
PxU8* contactPoints; //Start index/ptr for contact points
PxReal* contactForces; //Start index/ptr for contact forces
PxU8 nbContacts; //Num contacts
PxU8 nbPatches; //Num patches
PxU8 statusFlag; //Status flag (has touch etc.)
PxU8 prevPatches; //Previous number of patches
PX_FORCE_INLINE PxU32* getInternalFaceIndice()
{
return reinterpret_cast<PxU32*>(contactForces + nbContacts);
}
}
PX_ALIGN_SUFFIX(16);
struct /*PX_ALIGN_PREFIX(16)*/ PxsContactManagerPersistency
{
PxU8 mPrevPatches;
PxU8 mNbFrictionPatches;
PxU8 mNbPrevFrictionPatches;
}
/*PX_ALIGN_SUFFIX(16)*/;
}
#endif //PXG_CONTACT_MANAGER_H

View File

@ -0,0 +1,339 @@
//
// 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-2021 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 PXS_CONTEXT_H
#define PXS_CONTEXT_H
#include "PxVisualizationParameter.h"
#include "PxSceneDesc.h"
#include "CmPool.h"
#include "PxvNphaseImplementationContext.h"
#include "PxvSimStats.h"
#include "PxsContactManager.h"
#include "PxcNpBatch.h"
#include "PxcConstraintBlockStream.h"
#include "PxcNpCacheStreamPair.h"
#include "PxcNpMemBlockPool.h"
#include "CmRenderOutput.h"
#include "CmUtils.h"
#include "CmTask.h"
#include "PxContactModifyCallback.h"
#include "PxsTransformCache.h"
#include "GuPersistentContactManifold.h"
#include "DyArticulation.h"
#if PX_SUPPORT_GPU_PHYSX
namespace physx
{
class PxCudaContextManager;
}
#endif
namespace physx
{
class PxsRigidBody;
struct PxcConstraintBlock;
class PxsMaterialManager;
class PxsCCDContext;
struct PxsContactManagerOutput;
struct PxvContactManagerTouchEvent;
namespace Cm
{
class FlushPool;
}
namespace IG
{
class SimpleIslandManager;
typedef PxU32 EdgeIndex;
}
enum PxsTouchEventCount
{
PXS_LOST_TOUCH_COUNT = 0,
PXS_NEW_TOUCH_COUNT = 1,
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
// (but they could have lost touch in between)
PXS_PATCH_FOUND_COUNT = 3,
PXS_PATCH_LOST_COUNT = 4,
PXS_TOUCH_EVENT_COUNT = 5
};
class PxsContext : public Ps::UserAllocated, public PxcNpContext
{
PX_NOCOPY(PxsContext)
public:
PxsContext( const PxSceneDesc& desc, PxTaskManager*, Cm::FlushPool&, PxCudaContextManager*, PxU64 contextID);
~PxsContext();
void removeRigidBody(PxsRigidBody&);
Dy::Articulation* createArticulation();
void destroyArticulation(Dy::Articulation&);
void createTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback);
PxsContactManager* createContactManager(PxsContactManager* contactManager, const bool useCCD);
void createCache(Gu::Cache& cache, PxsContactManager* cm, PxU8 geomType0, PxU8 geomType1);
void destroyCache(Gu::Cache& cache);
void destroyContactManager(PxsContactManager* cm);
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
// Collision properties
PX_FORCE_INLINE PxContactModifyCallback* getContactModifyCallback() const { return mContactModifyCallback; }
PX_FORCE_INLINE void setContactModifyCallback(PxContactModifyCallback* c) { mContactModifyCallback = c; mNpImplementationContext->setContactModifyCallback(c);}
// resource-related
void setScratchBlock(void* addr, PxU32 size);
void setContactDistance(Ps::Array<PxReal, Ps::VirtualAllocator>* contactDistance);
// Task-related
void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation);
void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation);
void fetchUpdateContactManager();
void swapStreams();
void resetThreadContexts();
// Manager status change
bool getManagerTouchEventCount(int* newTouch, int* lostTouch, int* ccdTouch) const;
bool fillManagerTouchEvents(
PxvContactManagerTouchEvent* newTouch, PxI32& newTouchCount,
PxvContactManagerTouchEvent* lostTouch, PxI32& lostTouchCount,
PxvContactManagerTouchEvent* ccdTouch, PxI32& ccdTouchCount);
PX_FORCE_INLINE void getManagerPatchEventCount(PxU32& foundPatch, PxU32& lostPatch) const { foundPatch = mCMTouchEventCount[PXS_PATCH_FOUND_COUNT]; lostPatch = mCMTouchEventCount[PXS_PATCH_LOST_COUNT]; }
bool fillManagerPatchChangedEvents(
PxsContactManager** foundPatch, PxU32& foundPatchCount,
PxsContactManager** lostPatch, PxU32& lostPatchCount);
void beginUpdate();
// PX_ENABLE_SIM_STATS
PX_FORCE_INLINE PxvSimStats& getSimStats() { return mSimStats; }
PX_FORCE_INLINE const PxvSimStats& getSimStats() const { return mSimStats; }
PX_FORCE_INLINE Cm::FlushPool& getTaskPool() const { return mTaskPool; }
PX_FORCE_INLINE Cm::RenderBuffer& getRenderBuffer() { return mRenderBuffer; }
PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const;
void setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value);
PX_FORCE_INLINE void setVisualizationCullingBox(const PxBounds3& box) { mVisualizationCullingBox = box; }
PX_FORCE_INLINE const PxBounds3& getVisualizationCullingBox()const { return mVisualizationCullingBox; }
PX_FORCE_INLINE PxReal getRenderScale() const { return mVisualizationParams[PxVisualizationParameter::eSCALE]; }
Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); }
PX_FORCE_INLINE bool getPCM() const { return mPCM; }
PX_FORCE_INLINE bool getContactCacheFlag() const { return mContactCache; }
PX_FORCE_INLINE bool getCreateAveragePoint() const { return mCreateAveragePoint; }
// general stuff
void shiftOrigin(const PxVec3& shift);
void setCreateContactStream(bool to);
PX_FORCE_INLINE void setPCM(bool enabled) { mPCM = enabled; }
PX_FORCE_INLINE void setContactCache(bool enabled) { mContactCache = enabled; }
PX_FORCE_INLINE PxcScratchAllocator& getScratchAllocator() { return mScratchAllocator; }
PX_FORCE_INLINE PxsTransformCache& getTransformCache() { return *mTransformCache; }
PX_FORCE_INLINE PxReal* getContactDistance() { return mContactDistance->begin(); }
PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseImplementationContext() const
{
return mNpImplementationContext;
}
PX_FORCE_INLINE void setNphaseImplementationContext(PxvNphaseImplementationContext* ctx)
{
mNpImplementationContext = ctx;
}
PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseFallbackImplementationContext() const
{
return mNpFallbackImplementationContext;
}
PX_FORCE_INLINE void setNphaseFallbackImplementationContext(PxvNphaseImplementationContext* ctx)
{
mNpFallbackImplementationContext = ctx;
}
PxU32 getTotalCompressedContactSize() const { return mTotalCompressedCacheSize; }
PxU32 getMaxPatchCount() const { return mMaxPatches; }
PX_FORCE_INLINE PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>& getNpThreadContextPool()
{
return mNpThreadContextPool;
}
PX_FORCE_INLINE PxcNpThreadContext* getNpThreadContext()
{
// We may want to conditional compile to exclude this on single threaded implementations
// if it is determined to be a performance hit.
return mNpThreadContextPool.get();
}
PX_FORCE_INLINE void putNpThreadContext(PxcNpThreadContext* threadContext)
{ mNpThreadContextPool.put(threadContext); }
PX_FORCE_INLINE Ps::Mutex& getLock() { return mLock; }
PX_FORCE_INLINE PxTaskManager& getTaskManager()
{
PX_ASSERT(mTaskManager);
return *mTaskManager;
}
PX_FORCE_INLINE PxCudaContextManager* getCudaContextManager()
{
return mCudaContextManager;
}
PX_FORCE_INLINE void clearManagerTouchEvents();
PX_FORCE_INLINE Cm::PoolList<PxsContactManager, PxsContext>& getContactManagerPool()
{
return this->mContactManagerPool;
}
PX_FORCE_INLINE void setActiveContactManager(const PxsContactManager* manager)
{
const PxU32 index = manager->getIndex();
if (index >= mActiveContactManager.size())
{
PxU32 newSize = (2 * index + 256)&~255;
mActiveContactManager.resize(newSize);
}
mActiveContactManager.set(index);
//Record any pairs that have CCD enabled!
if (manager->getCCD())
{
if (index >= mActiveContactManagersWithCCD.size())
{
PxU32 newSize = (2 * index + 256)&~255;
mActiveContactManagersWithCCD.resize(newSize);
}
mActiveContactManagersWithCCD.set(index);
}
}
private:
void mergeCMDiscreteUpdateResults(PxBaseTask* continuation);
PxU32 mIndex;
// Threading
PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>
mNpThreadContextPool;
// Contact managers
Cm::PoolList<PxsContactManager, PxsContext> mContactManagerPool;
Ps::Pool<Gu::LargePersistentContactManifold> mManifoldPool;
Ps::Pool<Gu::SpherePersistentContactManifold> mSphereManifoldPool;
Cm::BitMap mActiveContactManager;
Cm::BitMap mActiveContactManagersWithCCD; //KS - adding to filter any pairs that had a touch
Cm::BitMap mContactManagersWithCCDTouch; //KS - adding to filter any pairs that had a touch
Cm::BitMap mContactManagerTouchEvent;
Cm::BitMap mContactManagerPatchChangeEvent;
PxU32 mCMTouchEventCount[PXS_TOUCH_EVENT_COUNT];
Ps::Mutex mLock;
PxContactModifyCallback* mContactModifyCallback;
// narrowphase platform-dependent implementations support
PxvNphaseImplementationContext* mNpImplementationContext;
PxvNphaseImplementationContext* mNpFallbackImplementationContext;
// debug rendering (CS TODO: MS would like to have these wrapped into a class)
PxReal mVisualizationParams[PxVisualizationParameter::eNUM_VALUES];
PxBounds3 mVisualizationCullingBox;
PxTaskManager* mTaskManager;
Cm::FlushPool& mTaskPool;
PxCudaContextManager* mCudaContextManager;
// PxU32 mTouchesLost;
// PxU32 mTouchesFound;
// PX_ENABLE_SIM_STATS
PxvSimStats mSimStats;
bool mPCM;
bool mContactCache;
bool mCreateAveragePoint;
PxsTransformCache* mTransformCache;
Ps::Array<PxReal, Ps::VirtualAllocator>* mContactDistance;
PxU32 mMaxPatches;
PxU32 mTotalCompressedCacheSize;
PxU64 mContextID;
friend class PxsCCDContext;
friend class PxsNphaseImplementationContext;
friend class PxgNphaseImplementationContext; //FDTODO ideally it shouldn't be here..
};
PX_FORCE_INLINE void PxsContext::clearManagerTouchEvents()
{
mContactManagerTouchEvent.clear();
mContactManagerPatchChangeEvent.clear();
for(PxU32 i = 0; i < PXS_TOUCH_EVENT_COUNT; ++i)
{
mCMTouchEventCount[i] = 0;
}
}
}
#endif

View File

@ -0,0 +1,98 @@
//
// 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-2021 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 PXS_DEFAULT_MEMORY_MANAGER_H
#define PXS_DEFAULT_MEMORY_MANAGER_H
#include "PxsMemoryManager.h"
#include "PsAllocator.h"
#include "PsArray.h"
namespace physx
{
class PxsDefaultMemoryAllocator : public Ps::VirtualAllocatorCallback
{
public:
PxsDefaultMemoryAllocator(const char* name = NULL)
{
PX_UNUSED(name);
#if 0 //PX_USE_NAMED_ALLOCATOR
if (name)
strcpy(mName, name);
else
strcpy(mName, "");
#endif
}
virtual ~PxsDefaultMemoryAllocator()
{
}
virtual void* allocate(const size_t newByteSize, const char* filename, const int line)
{
PX_UNUSED(line);
PX_UNUSED(filename);
#if 0 //PX_USE_NAMED_ALLOCATOR
return PX_ALLOC(newByteSize, mName);
#else
return PX_ALLOC(newByteSize, filename);
#endif
}
virtual void deallocate(void* ptr)
{
if (ptr)
PX_FREE(ptr);
}
#if 0 //PX_USE_NAMED_ALLOCATOR
char mName[32];
#endif
};
class PxsDefaultMemoryManager : public PxsMemoryManager
{
public:
virtual ~PxsDefaultMemoryManager();
virtual Ps::VirtualAllocatorCallback* createHostMemoryAllocator(const PxU32 gpuComputeVersion = 0);
virtual Ps::VirtualAllocatorCallback* createDeviceMemoryAllocator(const PxU32 gpuComputeVersion = 0);
virtual void destroyMemoryAllocator();
Ps::Array<Ps::VirtualAllocatorCallback*> mAllocators;
};
}
#endif

View File

@ -0,0 +1,66 @@
//
// 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-2021 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 PXS_HEAP_MEMORY_ALLOCATOR_H
#define PXS_HEAP_MEMORY_ALLOCATOR_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace shdfnd
{
class VirtualAllocatorCallback;
}
class PxErrorCallback;
class PxsHostMemoryAllocator;
class PxsHeapMemoryAllocator : public Ps::VirtualAllocatorCallback
{
public:
virtual ~PxsHeapMemoryAllocator(){}
virtual void* allocate(const size_t size, const char* file, const int line) = 0;
virtual void deallocate(void* ptr) = 0;
};
class PxsHeapMemoryAllocatorManager
{
public:
virtual ~PxsHeapMemoryAllocatorManager()
{
}
PxsHeapMemoryAllocator* mMappedMemoryAllocators;
};
}
#endif

View File

@ -0,0 +1,40 @@
//
// 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-2021 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 PXS_INCREMENTAL_CONSTRAINT_PARTITIONING_H
#define PXS_INCREMENTAL_CONSTRAINT_PARTITIONING_H
#include "PxsSimpleIslandManager.h"
namespace physx
{
}
#endif

View File

@ -0,0 +1,363 @@
//
// 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-2021 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 PXS_ISLAND_MANAGER_TYPES_H
#define PXS_ISLAND_MANAGER_TYPES_H
#include "CmPhysXCommon.h"
namespace physx
{
class PxsContactManager;
class PxsRigidBody;
namespace Dy
{
struct Constraint;
class Articulation;
}
typedef PxU32 NodeType;
typedef PxU32 EdgeType;
typedef PxU32 IslandType;
#define INVALID_NODE 0xffffffff
#define INVALID_EDGE 0xffffffff
#define INVALID_ISLAND 0xffffffff
namespace Dy
{
typedef size_t ArticulationLinkHandle;
}
//----------------------------------------------------------------------------//
template <class T, T INVLD> class PxsIslandManagerHook
{
friend class PxsIslandManager;
T index;
public:
static const T INVALID = INVLD;
PX_FORCE_INLINE PxsIslandManagerHook(): index(INVLD) {}
PX_FORCE_INLINE PxsIslandManagerHook(const T id): index(id) {}
PX_FORCE_INLINE PxsIslandManagerHook(const PxsIslandManagerHook<T,INVLD>& src) : index(src.index) {}
PX_FORCE_INLINE ~PxsIslandManagerHook(){}
PX_FORCE_INLINE bool isManaged() const { return index!=INVLD; }
private:
};
typedef PxsIslandManagerHook<NodeType,INVALID_NODE> PxsIslandManagerNodeHook;
typedef PxsIslandManagerHook<EdgeType,INVALID_EDGE> PxsIslandManagerEdgeHook;
typedef PxsIslandManagerHook<IslandType,INVALID_ISLAND> PxsIslandManagerIslandHook;
//----------------------------------------------------------------------------//
/**
\brief PxsIslandObjects contains arrays of all rigid bodies, articulations, contact managers, and constraints that
belong to all awake islands. The per array indices denoting the ownership per island are stored in PxsIslandIndices.
@see PxsIslandManager::getIslandObjects
*/
struct PxsIslandObjects
{
/**
\brief Array of all rigid bodies in all awake islands.
\note Each rigid body corresponds to the void* passed to PxsIslandManager::addBody. The PxsRigidBody ptr is computed
by adding the rigid body offset value (passed to PxsIslandManager::create) to the void* pointer
ie [(PxsRigidBody*)((PxU8*)owner + rigidBodyOffset)]
@see PxsIslandManager::addBody, PxsIslandManager::create
*/
PxsRigidBody*const* bodies;
/**
\brief Array of all articulation roots in all awake islands.
\note Each Articulation* corresponds to Dy::getArticulation(articLinkHandle) where
articLinkHandle is the handle passed to PxsIslandManager::setArticulationRootLinkHandle.
@see PxsIslandManager::setArticulationRootLinkHandle, Dy::getArticulation
*/
Dy::Articulation*const* articulations;
/**
\brief Array of all articulation roots in all awake islands.
\note Each void* corresponds to the void* passed to PxsIslandManager::setArticulationRootLinkHandle
@see PxsIslandManager::setArticulationRootLinkHandle
*/
void*const* articulationOwners;
/**
\brief Array of all contact managers in all awake islands.
@see PxsIslandManager::setEdgeRigidCM
*/
struct PxsIndexedContactManager* contactManagers;
/**
\brief Array of all constraints in all awake islands.
@see PxsIslandManager::setEdgeConstraint
*/
struct PxsIndexedConstraint* constraints;
PxsIslandObjects() : bodies(NULL), articulations(NULL), articulationOwners(NULL), contactManagers(NULL), constraints(NULL)
{
}
};
//----------------------------------------------------------------------------//
/**
\brief An array of PxsIslandIndices describes the rigid bodies, articulations, contacts and constraints that
belong to each island.
\note Given an array of PxsIslandIndices, the rigid bodies of the ith island span the inclusive range:
(PxsIslandObjects::bodies[PxsIslandIndices[i]], PxsIslandObjects::bodies[PxsIslandIndices[i+1]-1])
\note Given an array of PxsIslandIndices, the constraints of the ith island span the inclusive range:
(PxsIslandObjects::constraints[PxsIslandIndices[i]], PxsIslandObjects::constraints[PxsIslandIndices[i+1]-1])
@see PxsIslandObjects::getIslandIndices, PxsIslandObjects::getIslandCount
*/
class PxsIslandIndices
{
public:
PxsIslandIndices(){}
~PxsIslandIndices(){}
/**
\brief Return true if the corresponding island has a contact with a static rigid body.
*/
PX_FORCE_INLINE bool getHasStaticContact() const
{
return (1 & hasStaticContact) ? true : false;
}
/**
\brief The starting index of island rigid bodies in the array PxsIslandObjects::bodies
*/
NodeType bodies;
/**
\brief The starting index of island articulations in the arrays PxsIslandObjects::articulations and PxsIslandObjects::articulationOwners
\note The total number of articulations is clamped at 32767 on any platform that uses 16-bit handles.
*/
NodeType articulations : 8*sizeof(NodeType)-1;
private:
NodeType hasStaticContact : 1;
public:
/**
\brief The starting index of island contact managers in the array PxsIslandObjects::contactManagers.
*/
EdgeType contactManagers;
/**
\brief The starting index of island constraints in the array PxsIslandObjects::constraints.
\note islandId is for internal use only and is used for tracking islands that need a second pass.
*/
union
{
EdgeType constraints;
IslandType islandId;
};
//private:
/**
\brief Internal use only.
*/
PX_FORCE_INLINE void setHasStaticContact(const bool b)
{
hasStaticContact = NodeType(b ? 1 : 0);
}
};
PX_COMPILE_TIME_ASSERT(0==(0x07 & sizeof(PxsIslandIndices)));
//----------------------------------------------------------------------------//
typedef Dy::ArticulationLinkHandle PxsNodeType;
/**
\brief Each contact manager or constraint references two separate bodies, where
a body can be a dynamic rigid body, a kinematic rigid body, an articulation or a static.
The struct PxsIndexedInteraction describes the bodies that make up the pair.
*/
struct PxsIndexedInteraction
{
/**
\brief An enumerated list of all possible body types.
A body type is stored for each body in the pair.
*/
enum Enum
{
eBODY = 0,
eKINEMATIC = 1,
eARTICULATION = 2,
eWORLD = 3
};
/**
\brief An index describing how to access body0
\note If body0 is a dynamic (eBODY) rigid body then solverBody0 is an index into PxsIslandObjects::bodies.
\note If body0 is a kinematic (eKINEMATIC) rigid body then solverBody0 is an index into PxsIslandManager::getActiveKinematics.
\note If body0 is a static (eWORLD) then solverBody0 is PX_MAX_U32 or PX_MAX_U64, depending on the platform being 32- or 64-bit.
\note If body0 is an articulation then the articulation is found directly from Dy::getArticulation(articulation0)
*/
union
{
PxsNodeType solverBody0;
Dy::ArticulationLinkHandle articulation0;
};
/**
\brief An index describing how to access body1
\note If body1 is a dynamic (eBODY) rigid body then solverBody1 is an index into PxsIslandObjects::bodies.
\note If body1 is a kinematic (eKINEMATIC) rigid body then solverBody1 is an index into PxsIslandManager::getActiveKinematics.
\note If body1 is a static (eWORLD) then solverBody1 is PX_MAX_U32 or PX_MAX_U64, depending on the platform being 32- or 64-bit.
\note If body1 is an articulation then the articulation is found directly from Dy::getArticulation(articulation1)
*/
union
{
PxsNodeType solverBody1;
Dy::ArticulationLinkHandle articulation1;
};
/**
\brief The type (eBODY, eKINEMATIC etc) of body0
*/
PxU8 indexType0;
/**
\brief The type (eBODY, eKINEMATIC etc) of body1
*/
PxU8 indexType1;
PxU8 pad[2];
};
/**
@see PxsIslandObjects, PxsIndexedInteraction
*/
struct PxsIndexedContactManager : public PxsIndexedInteraction
{
/**
\brief The contact manager corresponds to the value set in PxsIslandManager::setEdgeRigidCM
*/
PxsContactManager* contactManager;
PxsIndexedContactManager(PxsContactManager* cm) : contactManager(cm) {}
};
#if !PX_X64
PX_COMPILE_TIME_ASSERT(0==(sizeof(PxsIndexedContactManager) & 0x0f));
#endif
/**
@see PxsIslandObjects, PxsIndexedInteraction
*/
struct PxsIndexedConstraint : public PxsIndexedInteraction
{
/**
\brief The constraint corresponds to the value set in PxsIslandManager::setEdgeConstraint
*/
Dy::Constraint* constraint;
PxsIndexedConstraint(Dy::Constraint* c) : constraint(c) {}
};
#if !PX_P64_FAMILY
PX_COMPILE_TIME_ASSERT(0==(sizeof(PxsIndexedConstraint) & 0x0f));
#endif
//----------------------------------------------------------------------------//
/**
\brief Any sleeping contact pair that finds itself in an awake island after 1st pass island gen
must participate in 2nd pass narrowphase so that contacts can be generated.
\note Contact managers in sleeping pairs are NULL until PxsIslandManager::setWokenPairContactManagers is complete.
@see PxsIslandManager::getNarrowPhaseSecondPassContactManagers, PxsIslandManager::getNumNarrowPhaseSecondPassContactManagers,
PxsIslandManager::setWokenPairContactManagers
*/
struct PxsNarrowPhaseSecondPassContactManager
{
/**
\brief The contact manager that is to participate in 2nd pass narrowphase.
\note This pointer is NULL after 1st pass island gen and remains NULL until PxsIslandManager::setWokenPairContactManagers
completes.
*/
PxsContactManager* mCM;
/**
\brief The corresponding entry in PxsIslandObjects::contactManagers.
\note All sleeping pairs have a null contact manager during 1st pass island gen. After 1st pass island gen completes,
the bodies to be woken are externally processed. Waking up bodies generates contact managers and passes the pointer to the
corresponding edge. So that the contact manager can be efficiently passed to PxsIslandObjects we store mEdgeId and mSolverCMId.
The contact manager pointers are set in PxsIslandManager::setWokenPairContactManagers
*/
EdgeType mSolverCMId; //Keeps a track of which entries in the solver islands temporarily have a null contact manager
/**
\brief The internal id of the corresponding edge.
*/
EdgeType mEdgeId;
};
} //namespace physx
#endif //PXS_ISLAND_MANAGER_TYPES_H

View File

@ -0,0 +1,78 @@
//
// 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-2021 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 PXS_ISLAND_NODEINDEX_H
#define PXS_ISLAND_NODEINDEX_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace IG
{
#define IG_INVALID_NODE 0x1FFFFFFu
class NodeIndex
{
private:
PxU32 ind;
public:
explicit PX_CUDA_CALLABLE PX_FORCE_INLINE NodeIndex(PxU32 id, PxU32 articLinkId) : ind((id << 7) | (articLinkId << 1) | 1)
{
}
explicit PX_CUDA_CALLABLE PX_FORCE_INLINE NodeIndex(PxU32 id = IG_INVALID_NODE) : ind((id << 7))
{
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 index() const { return ind >> 7; }
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 articulationLinkId() const { return ((ind >> 1) & 63); }
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 isArticulation() const { return ind & 1; }
PX_CUDA_CALLABLE PX_FORCE_INLINE bool isStaticBody() const { return (ind >> 7) == IG_INVALID_NODE; }
PX_CUDA_CALLABLE bool isValid() const { return (ind >> 7) != IG_INVALID_NODE; }
PX_CUDA_CALLABLE void setIndices(PxU32 index, PxU32 articLinkId) { ind = ((index << 7) | (articLinkId << 1) | 1); }
PX_CUDA_CALLABLE void setIndices(PxU32 index) { ind = ((index << 7)); }
PX_CUDA_CALLABLE bool operator < (const IG::NodeIndex& other) const { return ind < other.ind; }
PX_CUDA_CALLABLE bool operator <= (const IG::NodeIndex& other) const { return ind <= other.ind; }
PX_CUDA_CALLABLE bool operator == (const IG::NodeIndex& other) const { return ind == other.ind; }
};
}
}
#endif

View File

@ -0,0 +1,940 @@
//
// 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-2021 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 PXS_ISLAND_SIM_H
#define PXS_ISLAND_SIM_H
#include "CmPhysXCommon.h"
#include "foundation/PxAssert.h"
#include "PsArray.h"
#include "CmBitMap.h"
#include "CmPriorityQueue.h"
#include "CmBlockArray.h"
#include "PxsIslandNodeIndex.h"
namespace physx
{
namespace Dy
{
struct Constraint;
class ArticulationV;
}
namespace Sc
{
class ArticulationSim;
}
class PxsContactManager;
class PxsRigidBody;
struct PartitionEdge;
namespace IG
{
//This index is
#define IG_INVALID_ISLAND 0xFFFFFFFFu
#define IG_INVALID_EDGE 0xFFFFFFFFu
#define IG_INVALID_LINK 0xFFu
typedef PxU32 IslandId;
typedef PxU32 EdgeIndex;
typedef PxU32 EdgeInstanceIndex;
class IslandSim;
struct Edge
{
//Edge instances can be implicitly calculated based on this edge index, which is an offset into the array of edges.
//From that, the child edge index is simply the
//The constraint or contact referenced by this edge
enum EdgeType
{
eCONTACT_MANAGER,
eCONSTRAINT,
eEDGE_TYPE_COUNT
};
enum EdgeState
{
eINSERTED =1<<0,
ePENDING_DESTROYED =1<<1,
eACTIVE =1<<2,
eIN_DIRTY_LIST =1<<3,
eDESTROYED =1<<4,
eREPORT_ONLY_DESTROY=1<<5,
eACTIVATING =1<<6
};
//NodeIndex mNode1, mNode2;
EdgeType mEdgeType;
PxU16 mEdgeState;
EdgeIndex mNextIslandEdge, mPrevIslandEdge;
PX_FORCE_INLINE void setInserted() { mEdgeState |= (eINSERTED); }
PX_FORCE_INLINE void clearInserted() { mEdgeState &= (~eINSERTED); }
PX_FORCE_INLINE void clearDestroyed() { mEdgeState &=(~eDESTROYED);}
PX_FORCE_INLINE void setPendingDestroyed() { mEdgeState |= ePENDING_DESTROYED; }
PX_FORCE_INLINE void clearPendingDestroyed() { mEdgeState &= (~ePENDING_DESTROYED); }
PX_FORCE_INLINE void activateEdge() { mEdgeState |= eACTIVE; }
PX_FORCE_INLINE void deactivateEdge() { mEdgeState &= (~eACTIVE); }
PX_FORCE_INLINE void markInDirtyList() { mEdgeState |= (eIN_DIRTY_LIST); }
PX_FORCE_INLINE void clearInDirtyList() { mEdgeState &= (~eIN_DIRTY_LIST); }
PX_FORCE_INLINE void setReportOnlyDestroy() { mEdgeState |= (eREPORT_ONLY_DESTROY); }
PX_FORCE_INLINE void clearReportOnlyDestroy() { mEdgeState &= (~eREPORT_ONLY_DESTROY); }
public:
Edge() : mEdgeType(Edge::eCONTACT_MANAGER), mEdgeState(eDESTROYED),
mNextIslandEdge(IG_INVALID_EDGE), mPrevIslandEdge(IG_INVALID_EDGE)
{
}
PX_FORCE_INLINE bool isInserted() const { return !!(mEdgeState & eINSERTED);}
PX_FORCE_INLINE bool isDestroyed() const { return !!(mEdgeState & eDESTROYED); }
PX_FORCE_INLINE bool isPendingDestroyed() const { return !!(mEdgeState & ePENDING_DESTROYED); }
PX_FORCE_INLINE bool isActive() const { return !!(mEdgeState & eACTIVE); }
PX_FORCE_INLINE bool isInDirtyList() const { return !!(mEdgeState & eIN_DIRTY_LIST); }
PX_FORCE_INLINE EdgeType getEdgeType() const { return mEdgeType; }
//PX_FORCE_INLINE const NodeIndex getIndex1() const { return mNode1; }
//PX_FORCE_INLINE const NodeIndex getIndex2() const { return mNode2; }
PX_FORCE_INLINE bool isReportOnlyDestroy() { return !!(mEdgeState & eREPORT_ONLY_DESTROY); }
};
struct EdgeInstance
{
EdgeInstanceIndex mNextEdge, mPrevEdge; //The next edge instance in this node's list of edge instances
EdgeInstance() : mNextEdge(IG_INVALID_EDGE), mPrevEdge(IG_INVALID_EDGE)
{
}
};
template<typename Handle>
class HandleManager
{
Ps::Array<Handle> mFreeHandles;
Handle mCurrentHandle;
public:
HandleManager() : mFreeHandles(PX_DEBUG_EXP("FreeHandles")), mCurrentHandle(0)
{
}
~HandleManager(){}
Handle getHandle()
{
if(mFreeHandles.size())
{
Handle handle = mFreeHandles.popBack();
PX_ASSERT(isValidHandle(handle));
return handle;
}
return mCurrentHandle++;
}
bool isNotFreeHandle(Handle handle)
{
for(PxU32 a = 0; a < mFreeHandles.size(); ++a)
{
if(mFreeHandles[a] == handle)
return false;
}
return true;
}
void freeHandle(Handle handle)
{
PX_ASSERT(isValidHandle(handle));
PX_ASSERT(isNotFreeHandle(handle));
if(handle == mCurrentHandle)
mCurrentHandle--;
else
mFreeHandles.pushBack(handle);
}
bool isValidHandle(Handle handle)
{
return handle < mCurrentHandle;
}
PX_FORCE_INLINE PxU32 getTotalHandles() const { return mCurrentHandle; }
};
class Node
{
public:
enum NodeType
{
eRIGID_BODY_TYPE,
eARTICULATION_TYPE,
eTYPE_COUNT
};
enum State
{
eREADY_FOR_SLEEPING = 1u << 0, //! Ready to go to sleep
eACTIVE = 1u << 1, //! Active
eKINEMATIC = 1u << 2, //! Kinematic
eDELETED = 1u << 3, //! Is pending deletion
eDIRTY = 1u << 4, //! Is dirty (i.e. lost a connection)
eACTIVATING = 1u << 5, //! Is in the activating list
eDEACTIVATING = 1u << 6 //! It is being forced to deactivate this frame
};
EdgeInstanceIndex mFirstEdgeIndex;
PxU8 mFlags;
PxU8 mType;
PxU16 mStaticTouchCount;
//PxU32 mActiveNodeIndex; //! Look-up for this node in the active nodes list, activating list or deactivating list...
NodeIndex mNextNode, mPrevNode;
//A counter for the number of active references to this body. Whenever an edge is activated, this is incremented.
//Whenver an edge is deactivated, this is decremented. This is used for kinematic bodies to determine if they need
//to be in the active kinematics list
PxU32 mActiveRefCount;
//A node can correspond with either a rigid body or an articulation or softBody
union
{
PxsRigidBody* mRigidBody;
Dy::ArticulationV* mLLArticulation;
};
PX_FORCE_INLINE Node() : mFirstEdgeIndex(IG_INVALID_EDGE), mFlags(eDELETED), mType(eRIGID_BODY_TYPE),
mStaticTouchCount(0), mActiveRefCount(0), mRigidBody(NULL)
{
}
PX_FORCE_INLINE ~Node() {}
PX_FORCE_INLINE void reset()
{
mFirstEdgeIndex = IG_INVALID_EDGE;
mFlags = eDELETED;
mRigidBody = NULL;
mActiveRefCount = 0;
mStaticTouchCount = 0;
}
PX_FORCE_INLINE void setRigidBody(PxsRigidBody* body) { mRigidBody = body; }
PX_FORCE_INLINE PxsRigidBody* getRigidBody() const { return mRigidBody; }
PX_FORCE_INLINE Dy::ArticulationV* getArticulation() const { return mLLArticulation; }
PX_FORCE_INLINE void setActive() { mFlags |= eACTIVE; }
PX_FORCE_INLINE void clearActive() { mFlags &= ~eACTIVE; }
PX_FORCE_INLINE void setActivating() { mFlags |= eACTIVATING; }
PX_FORCE_INLINE void clearActivating() { mFlags &= ~eACTIVATING; }
PX_FORCE_INLINE void setDeactivating() { mFlags |= eDEACTIVATING; }
PX_FORCE_INLINE void clearDeactivating() { mFlags &= (~eDEACTIVATING); }
//Activates a body/node.
PX_FORCE_INLINE void setIsReadyForSleeping() { mFlags |= eREADY_FOR_SLEEPING; }
PX_FORCE_INLINE void clearIsReadyForSleeping(){ mFlags &= (~eREADY_FOR_SLEEPING);}
PX_FORCE_INLINE void setIsDeleted(){mFlags |= eDELETED; }
PX_FORCE_INLINE void setKinematicFlag() {PX_ASSERT(!isKinematic()); mFlags |= eKINEMATIC;}
PX_FORCE_INLINE void clearKinematicFlag(){ PX_ASSERT(isKinematic()); mFlags &= (~eKINEMATIC);}
PX_FORCE_INLINE void markDirty(){mFlags |= eDIRTY;}
PX_FORCE_INLINE void clearDirty(){mFlags &= (~eDIRTY);}
public:
PX_FORCE_INLINE bool isActive() const { return !!(mFlags & eACTIVE); }
PX_FORCE_INLINE bool isActiveOrActivating() const { return !!(mFlags & (eACTIVE | eACTIVATING)); }
PX_FORCE_INLINE bool isActivating() const { return !!(mFlags & eACTIVATING); }
PX_FORCE_INLINE bool isDeactivating() const { return !!(mFlags & eDEACTIVATING); }
PX_FORCE_INLINE bool isKinematic() const { return !!(mFlags & eKINEMATIC); }
PX_FORCE_INLINE bool isDeleted() const { return !!(mFlags & eDELETED); }
PX_FORCE_INLINE bool isDirty() const { return !!(mFlags & eDIRTY); }
PX_FORCE_INLINE bool isReadyForSleeping() const { return !!(mFlags & eREADY_FOR_SLEEPING); }
PX_FORCE_INLINE NodeType getNodeType() const { return NodeType(mType); }
friend class SimpleIslandManager;
};
struct Island
{
NodeIndex mRootNode;
NodeIndex mLastNode;
PxU32 mSize[Node::eTYPE_COUNT];
PxU32 mActiveIndex;
EdgeIndex mFirstEdge[Edge::eEDGE_TYPE_COUNT], mLastEdge[Edge::eEDGE_TYPE_COUNT];
PxU32 mEdgeCount[Edge::eEDGE_TYPE_COUNT];
Island() : mActiveIndex(IG_INVALID_ISLAND)
{
for(PxU32 a = 0; a < Edge::eEDGE_TYPE_COUNT; ++a)
{
mFirstEdge[a] = IG_INVALID_EDGE;
mLastEdge[a] = IG_INVALID_EDGE;
mEdgeCount[a] = 0;
}
for(PxU32 a = 0; a < Node::eTYPE_COUNT; ++a)
{
mSize[a] = 0;
}
}
};
struct TraversalState
{
NodeIndex mNodeIndex;
PxU32 mCurrentIndex;
PxU32 mPrevIndex;
PxU32 mDepth;
TraversalState()
{
}
TraversalState(NodeIndex nodeIndex, PxU32 currentIndex, PxU32 prevIndex, PxU32 depth) :
mNodeIndex(nodeIndex), mCurrentIndex(currentIndex), mPrevIndex(prevIndex), mDepth(depth)
{
}
};
struct QueueElement
{
TraversalState* mState;
PxU32 mHopCount;
QueueElement()
{
}
QueueElement(TraversalState* state, PxU32 hopCount) : mState(state), mHopCount(hopCount)
{
}
};
struct NodeComparator
{
NodeComparator()
{
}
bool operator() (const QueueElement& node0, const QueueElement& node1) const
{
return node0.mHopCount < node1.mHopCount;
}
private:
NodeComparator& operator = (const NodeComparator&);
};
class IslandSim
{
HandleManager<IslandId> mIslandHandles; //! Handle manager for islands
Ps::Array<Node> mNodes; //! The nodes used in the constraint graph
Ps::Array<PxU32> mActiveNodeIndex; //! The active node index for each node
Cm::BlockArray<Edge> mEdges;
Cm::BlockArray<EdgeInstance> mEdgeInstances; //! Edges used to connect nodes in the constraint graph
Ps::Array<Island> mIslands; //! The array of islands
Ps::Array<PxU32> mIslandStaticTouchCount; //! Array of static touch counts per-island
Ps::Array<NodeIndex> mActiveNodes[Node::eTYPE_COUNT]; //! An array of active nodes
Ps::Array<NodeIndex> mActiveKinematicNodes; //! An array of active or referenced kinematic nodes
Ps::Array<EdgeIndex> mActivatedEdges[Edge::eEDGE_TYPE_COUNT]; //! An array of active edges
PxU32 mActiveEdgeCount[Edge::eEDGE_TYPE_COUNT];
Ps::Array<PxU32> mHopCounts; //! The observed number of "hops" from a given node to its root node. May be inaccurate but used to accelerate searches.
Ps::Array<NodeIndex> mFastRoute; //! The observed last route from a given node to the root node. We try the fast route (unless its broken) before trying others.
Ps::Array<IslandId> mIslandIds; //! The array of per-node island ids
Cm::BitMap mIslandAwake; //! Indicates whether an island is awake or not
Cm::BitMap mActiveContactEdges;
//An array of active islands
Ps::Array<IslandId> mActiveIslands;
PxU32 mInitialActiveNodeCount[Edge::eEDGE_TYPE_COUNT];
Ps::Array<NodeIndex> mNodesToPutToSleep[Node::eTYPE_COUNT];
//Input to this frame's island management (changed nodes/edges)
//Input list of changes observed this frame. If there no changes, no work to be done.
Ps::Array<EdgeIndex> mDirtyEdges[Edge::eEDGE_TYPE_COUNT];
//Dirty nodes. These nodes lost at least one connection so we need to recompute islands from these nodes
//Ps::Array<NodeIndex> mDirtyNodes;
Cm::BitMap mDirtyMap;
PxU32 mLastMapIndex;
//An array of nodes to activate
Ps::Array<NodeIndex> mActivatingNodes;
Ps::Array<EdgeIndex> mDestroyedEdges;
Ps::Array<IslandId> mTempIslandIds;
//Temporary, transient data used for traversals. TODO - move to PxsSimpleIslandManager. Or if we keep it here, we can
//process multiple island simulations in parallel
Cm::PriorityQueue<QueueElement, NodeComparator>
mPriorityQueue; //! Priority queue used for graph traversal
Ps::Array<TraversalState> mVisitedNodes; //! The list of nodes visited in the current traversal
Cm::BitMap mVisitedState; //! Indicates whether a node has been visited
Ps::Array<EdgeIndex> mIslandSplitEdges[Edge::eEDGE_TYPE_COUNT];
Ps::Array<EdgeIndex> mDeactivatingEdges[Edge::eEDGE_TYPE_COUNT];
Ps::Array<PartitionEdge*>* mFirstPartitionEdges;
Cm::BlockArray<NodeIndex>& mEdgeNodeIndices;
Ps::Array<physx::PartitionEdge*>* mDestroyedPartitionEdges;
PxU32* mNpIndexPtr;
PxU64 mContextId;
public:
IslandSim(Ps::Array<PartitionEdge*>* firstPartitionEdges, Cm::BlockArray<NodeIndex>& edgeNodeIndices, Ps::Array<PartitionEdge*>* destroyedPartitionEdges, PxU64 contextID);
~IslandSim() {}
void resize(const PxU32 nbNodes, const PxU32 nbContactManagers, const PxU32 nbConstraints);
void addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive, NodeIndex nodeIndex);
void addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive, NodeIndex nodeIndex);
void addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, EdgeIndex handle);
void addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, EdgeIndex handle);
void activateNode(NodeIndex index);
void deactivateNode(NodeIndex index);
void putNodeToSleep(NodeIndex index);
void removeConnection(EdgeIndex edgeIndex);
PX_FORCE_INLINE PxU32 getNbNodes() const { return mNodes.size(); }
PX_FORCE_INLINE PxU32 getNbActiveNodes(Node::NodeType type) const { return mActiveNodes[type].size(); }
PX_FORCE_INLINE const NodeIndex* getActiveNodes(Node::NodeType type) const { return mActiveNodes[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActiveKinematics() const { return mActiveKinematicNodes.size(); }
PX_FORCE_INLINE const NodeIndex* getActiveKinematics() const { return mActiveKinematicNodes.begin(); }
PX_FORCE_INLINE PxU32 getNbNodesToActivate(Node::NodeType type) const { return mActiveNodes[type].size() - mInitialActiveNodeCount[type]; }
PX_FORCE_INLINE const NodeIndex* getNodesToActivate(Node::NodeType type) const { return mActiveNodes[type].begin() + mInitialActiveNodeCount[type]; }
PX_FORCE_INLINE PxU32 getNbNodesToDeactivate(Node::NodeType type) const { return mNodesToPutToSleep[type].size(); }
PX_FORCE_INLINE const NodeIndex* getNodesToDeactivate(Node::NodeType type) const { return mNodesToPutToSleep[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActivatedEdges(Edge::EdgeType type) const { return mActivatedEdges[type].size(); }
PX_FORCE_INLINE const EdgeIndex* getActivatedEdges(Edge::EdgeType type) const { return mActivatedEdges[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActiveEdges(Edge::EdgeType type) const { return mActiveEdgeCount[type]; }
PX_FORCE_INLINE PartitionEdge* getFirstPartitionEdge(IG::EdgeIndex edgeIndex) const { return (*mFirstPartitionEdges)[edgeIndex]; }
PX_FORCE_INLINE void setFirstPartitionEdge(IG::EdgeIndex edgeIndex, PartitionEdge* partitionEdge) { (*mFirstPartitionEdges)[edgeIndex] = partitionEdge; }
//PX_FORCE_INLINE const EdgeIndex* getActiveEdges(Edge::EdgeType type) const { return mActiveEdges[type].begin(); }
PX_FORCE_INLINE PxsRigidBody* getRigidBody(NodeIndex nodeIndex) const
{
const Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.mType == Node::eRIGID_BODY_TYPE);
return node.mRigidBody;
}
PX_FORCE_INLINE Dy::ArticulationV* getLLArticulation(NodeIndex nodeIndex) const
{
const Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.mType == Node::eARTICULATION_TYPE);
return node.mLLArticulation;
}
PX_FORCE_INLINE void clearDeactivations()
{
mNodesToPutToSleep[0].forceSize_Unsafe(0);
mNodesToPutToSleep[1].forceSize_Unsafe(0);
mDeactivatingEdges[0].forceSize_Unsafe(0);
mDeactivatingEdges[1].forceSize_Unsafe(0);
}
PX_FORCE_INLINE const Island& getIsland(IG::IslandId islandIndex) const { return mIslands[islandIndex]; }
PX_FORCE_INLINE PxU32 getNbActiveIslands() const { return mActiveIslands.size(); }
PX_FORCE_INLINE const IslandId* getActiveIslands() const { return mActiveIslands.begin(); }
PX_FORCE_INLINE PxU32 getNbDeactivatingEdges(const IG::Edge::EdgeType edgeType) const { return mDeactivatingEdges[edgeType].size(); }
PX_FORCE_INLINE const EdgeIndex* getDeactivatingEdges(const IG::Edge::EdgeType edgeType) const { return mDeactivatingEdges[edgeType].begin(); }
PX_FORCE_INLINE PxU32 getNbDestroyedEdges() const { return mDestroyedEdges.size(); }
PX_FORCE_INLINE const EdgeIndex* getDestroyedEdges() const { return mDestroyedEdges.begin(); }
PX_FORCE_INLINE PxU32 getNbDestroyedPartitionEdges() const { return mDestroyedPartitionEdges->size(); }
PX_FORCE_INLINE const PartitionEdge*const * getDestroyedPartitionEdges() const { return mDestroyedPartitionEdges->begin(); }
PX_FORCE_INLINE PartitionEdge** getDestroyedPartitionEdges() { return mDestroyedPartitionEdges->begin(); }
PX_FORCE_INLINE PxU32 getNbDirtyEdges(IG::Edge::EdgeType type) const { return mDirtyEdges[type].size(); }
PX_FORCE_INLINE const EdgeIndex* getDirtyEdges(IG::Edge::EdgeType type) const { return mDirtyEdges[type].begin(); }
PX_FORCE_INLINE const Edge& getEdge(const EdgeIndex edgeIndex) const { return mEdges[edgeIndex]; }
PX_FORCE_INLINE Edge& getEdge(const EdgeIndex edgeIndex) { return mEdges[edgeIndex]; }
PX_FORCE_INLINE const Node& getNode(const NodeIndex& nodeIndex) const { return mNodes[nodeIndex.index()]; }
PX_FORCE_INLINE const Island& getIsland(const NodeIndex& nodeIndex) const { PX_ASSERT(mIslandIds[nodeIndex.index()] != IG_INVALID_ISLAND); return mIslands[mIslandIds[nodeIndex.index()]]; }
PX_FORCE_INLINE PxU32 getIslandStaticTouchCount(const NodeIndex& nodeIndex) const { PX_ASSERT(mIslandIds[nodeIndex.index()] != IG_INVALID_ISLAND); return mIslandStaticTouchCount[mIslandIds[nodeIndex.index()]]; }
PX_FORCE_INLINE const Cm::BitMap& getActiveContactManagerBitmap() const { return mActiveContactEdges; }
PX_FORCE_INLINE PxU32 getActiveNodeIndex(const NodeIndex& nodeIndex) const { PxU32 activeNodeIndex = mActiveNodeIndex[nodeIndex.index()]; return activeNodeIndex;}
PX_FORCE_INLINE const PxU32* getActiveNodeIndex() const { return mActiveNodeIndex.begin(); }
PX_FORCE_INLINE PxU32 getNbActiveNodeIndex() const { return mActiveNodeIndex.size(); }
void setKinematic(IG::NodeIndex nodeIndex);
void setDynamic(IG::NodeIndex nodeIndex);
PX_FORCE_INLINE void setEdgeNodeIndexPtr(PxU32* ptr) { mNpIndexPtr = ptr; }
PX_FORCE_INLINE NodeIndex getNodeIndex1(IG::EdgeIndex index) const { return mEdgeNodeIndices[2 * index]; }
PX_FORCE_INLINE NodeIndex getNodeIndex2(IG::EdgeIndex index) const { return mEdgeNodeIndices[2 * index + 1]; }
PX_FORCE_INLINE PxU32* getEdgeNodeIndexPtr() const { return mNpIndexPtr; }
PX_FORCE_INLINE PxU64 getContextId() const { return mContextId; }
PxU32 getNbIslands() const { return mIslandStaticTouchCount.size(); }
const PxU32* getIslandStaticTouchCount() const { return mIslandStaticTouchCount.begin(); }
const PxU32* getIslandIds() const { return mIslandIds.begin(); }
bool checkInternalConsistency();
private:
void insertNewEdges();
void removeDestroyedEdges();
void wakeIslands();
void wakeIslands2();
void processNewEdges();
void processLostEdges(Ps::Array<NodeIndex>& destroyedNodes, bool allowDeactivation, bool permitKinematicDeactivation, PxU32 dirtyNodeLimit);
void removeConnectionInternal(EdgeIndex edgeIndex);
void addConnection(NodeIndex nodeHandle1, NodeIndex nodeHandle2, Edge::EdgeType edgeType, EdgeIndex handle);
void addConnectionToGraph(EdgeIndex index);
void removeConnectionFromGraph(EdgeIndex edgeIndex);
void connectEdge(EdgeInstance& instance, EdgeInstanceIndex edgeIndex, Node& source, NodeIndex destination);
void disconnectEdge(EdgeInstance& instance, EdgeInstanceIndex edgeIndex, Node& node);
//Merges 2 islands together. The returned id is the id of the merged island
IslandId mergeIslands(IslandId island0, IslandId island1, NodeIndex node0, NodeIndex node1);
void mergeIslandsInternal(Island& island0, Island& island1, IslandId islandId0, IslandId islandId1, NodeIndex node0, NodeIndex node1);
IslandSim& operator = (const IslandSim&);
IslandSim(const IslandSim&);
void unwindRoute(PxU32 traversalIndex, NodeIndex lastNode, PxU32 hopCount, IslandId id);
void activateIsland(IslandId island);
void deactivateIsland(IslandId island);
bool canFindRoot(NodeIndex startNode, NodeIndex targetNode, Ps::Array<NodeIndex>* visitedNodes);
bool tryFastPath(NodeIndex startNode, NodeIndex targetNode, IslandId islandId);
bool findRoute(NodeIndex startNode, NodeIndex targetNode, IslandId islandId);
bool isPathTo(NodeIndex startNode, NodeIndex targetNode);
void addNode(bool isActive, bool isKinematic, Node::NodeType type, NodeIndex nodeIndex);
void activateNodeInternal(NodeIndex index);
void deactivateNodeInternal(NodeIndex index);
PX_FORCE_INLINE void notifyReadyForSleeping(const NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
//PX_ASSERT(node.isActive());
node.setIsReadyForSleeping();
}
PX_FORCE_INLINE void notifyNotReadyForSleeping(const NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.isActive() || node.isActivating());
node.clearIsReadyForSleeping();
}
PX_FORCE_INLINE void markIslandActive(IslandId islandId)
{
Island& island = mIslands[islandId];
PX_ASSERT(!mIslandAwake.test(islandId));
PX_ASSERT(island.mActiveIndex == IG_INVALID_ISLAND);
mIslandAwake.set(islandId);
island.mActiveIndex = mActiveIslands.size();
mActiveIslands.pushBack(islandId);
}
PX_FORCE_INLINE void markIslandInactive(IslandId islandId)
{
Island& island = mIslands[islandId];
PX_ASSERT(mIslandAwake.test(islandId));
PX_ASSERT(island.mActiveIndex != IG_INVALID_ISLAND);
PX_ASSERT(mActiveIslands[island.mActiveIndex] == islandId);
IslandId replaceId = mActiveIslands[mActiveIslands.size()-1];
PX_ASSERT(mIslandAwake.test(replaceId));
Island& replaceIsland = mIslands[replaceId];
replaceIsland.mActiveIndex = island.mActiveIndex;
mActiveIslands[island.mActiveIndex] = replaceId;
mActiveIslands.forceSize_Unsafe(mActiveIslands.size()-1);
island.mActiveIndex = IG_INVALID_ISLAND;
mIslandAwake.reset(islandId);
}
PX_FORCE_INLINE void markKinematicActive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(node.isKinematic());
if(node.mActiveRefCount == 0 && mActiveNodeIndex[index.index()] == IG_INVALID_NODE)
{
//PX_ASSERT(mActiveNodeIndex[index.index()] == IG_INVALID_NODE);
//node.mActiveNodeIndex = mActiveKinematicNodes.size();
mActiveNodeIndex[index.index()] = mActiveKinematicNodes.size();
mActiveKinematicNodes.pushBack(index);
}
}
PX_FORCE_INLINE void markKinematicInactive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
PX_ASSERT(mActiveKinematicNodes[mActiveNodeIndex[index.index()]].index() == index.index());
if(node.mActiveRefCount == 0)
{
//Only remove from active kinematic list if it has no active contacts referencing it *and* it is asleep
if(mActiveNodeIndex[index.index()] != IG_INVALID_NODE)
{
//Need to verify active node index because there is an edge case where a node could be woken, then put to
//sleep in the same frame. This would mean that it would not have an active index at this stage.
NodeIndex replaceIndex = mActiveKinematicNodes.back();
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == mActiveKinematicNodes.size()-1);
mActiveNodeIndex[replaceIndex.index()] = mActiveNodeIndex[index.index()];
mActiveKinematicNodes[mActiveNodeIndex[index.index()]] = replaceIndex;
mActiveKinematicNodes.forceSize_Unsafe(mActiveKinematicNodes.size()-1);
mActiveNodeIndex[index.index()] = IG_INVALID_NODE;
}
}
}
PX_FORCE_INLINE void markActive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] == IG_INVALID_NODE);
mActiveNodeIndex[index.index()] = mActiveNodes[node.mType].size();
mActiveNodes[node.mType].pushBack(index);
}
PX_FORCE_INLINE void markInactive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
Ps::Array<NodeIndex>& activeNodes = mActiveNodes[node.mType];
PX_ASSERT(activeNodes[mActiveNodeIndex[index.index()]].index() == index.index());
const PxU32 initialActiveNodeCount = mInitialActiveNodeCount[node.mType];
if(mActiveNodeIndex[index.index()] < initialActiveNodeCount)
{
//It's in the initial active node set. We retain a list of active nodes, where the existing active nodes
//are at the beginning of the array and the newly activated nodes are at the end of the array...
//The solution is to move the node to the end of the initial active node list in this case
PxU32 activeNodeIndex = mActiveNodeIndex[index.index()];
NodeIndex replaceIndex = activeNodes[initialActiveNodeCount-1];
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == initialActiveNodeCount-1);
mActiveNodeIndex[index.index()] = mActiveNodeIndex[replaceIndex.index()];
mActiveNodeIndex[replaceIndex.index()] = activeNodeIndex;
activeNodes[activeNodeIndex] = replaceIndex;
activeNodes[mActiveNodeIndex[index.index()]] = index;
mInitialActiveNodeCount[node.mType]--;
}
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
PX_ASSERT(activeNodes[mActiveNodeIndex[index.index()]].index() == index.index());
NodeIndex replaceIndex = activeNodes.back();
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == activeNodes.size()-1);
mActiveNodeIndex[replaceIndex.index()] = mActiveNodeIndex[index.index()];
activeNodes[mActiveNodeIndex[index.index()]] = replaceIndex;
activeNodes.forceSize_Unsafe(activeNodes.size()-1);
mActiveNodeIndex[index.index()] = IG_INVALID_NODE;
}
PX_FORCE_INLINE void markEdgeActive(EdgeIndex index)
{
Edge& edge = mEdges[index];
PX_ASSERT((edge.mEdgeState & Edge::eACTIVATING) == 0);
edge.mEdgeState |= Edge::eACTIVATING;
mActivatedEdges[edge.mEdgeType].pushBack(index);
mActiveEdgeCount[edge.mEdgeType]++;
//Set the active bit...
if(edge.mEdgeType == Edge::eCONTACT_MANAGER)
mActiveContactEdges.set(index);
NodeIndex nodeIndex1 = mEdgeNodeIndices[2 * index];
NodeIndex nodeIndex2 = mEdgeNodeIndices[2 * index + 1];
if (nodeIndex1.index() != IG_INVALID_NODE && nodeIndex2.index() != IG_INVALID_NODE)
{
PX_ASSERT((!mNodes[nodeIndex1.index()].isKinematic()) || (!mNodes[nodeIndex2.index()].isKinematic()) || edge.getEdgeType() == IG::Edge::eCONTACT_MANAGER);
{
Node& node = mNodes[nodeIndex1.index()];
if(node.mActiveRefCount == 0 && node.isKinematic() && !(node.isActive() || node.isActivating()))
{
//Add to active kinematic list
markKinematicActive(nodeIndex1);
}
node.mActiveRefCount++;
}
{
Node& node = mNodes[nodeIndex2.index()];
if(node.mActiveRefCount == 0 && node.isKinematic() && !(node.isActive() || node.isActivating()))
{
//Add to active kinematic list
markKinematicActive(nodeIndex2);
}
node.mActiveRefCount++;
}
}
}
void removeEdgeFromActivatingList(EdgeIndex index);
PX_FORCE_INLINE void removeEdgeFromIsland(Island& island, EdgeIndex edgeIndex)
{
Edge& edge = mEdges[edgeIndex];
if(edge.mNextIslandEdge != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[edge.mNextIslandEdge].mPrevIslandEdge == edgeIndex);
mEdges[edge.mNextIslandEdge].mPrevIslandEdge = edge.mPrevIslandEdge;
}
else
{
PX_ASSERT(island.mLastEdge[edge.mEdgeType] == edgeIndex);
island.mLastEdge[edge.mEdgeType] = edge.mPrevIslandEdge;
}
if(edge.mPrevIslandEdge != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[edge.mPrevIslandEdge].mNextIslandEdge == edgeIndex);
mEdges[edge.mPrevIslandEdge].mNextIslandEdge = edge.mNextIslandEdge;
}
else
{
PX_ASSERT(island.mFirstEdge[edge.mEdgeType] == edgeIndex);
island.mFirstEdge[edge.mEdgeType] = edge.mNextIslandEdge;
}
island.mEdgeCount[edge.mEdgeType]--;
edge.mNextIslandEdge = edge.mPrevIslandEdge = IG_INVALID_EDGE;
}
PX_FORCE_INLINE void addEdgeToIsland(Island& island, EdgeIndex edgeIndex)
{
Edge& edge = mEdges[edgeIndex];
PX_ASSERT(edge.mNextIslandEdge == IG_INVALID_EDGE && edge.mPrevIslandEdge == IG_INVALID_EDGE);
if(island.mLastEdge[edge.mEdgeType] != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[island.mLastEdge[edge.mEdgeType]].mNextIslandEdge == IG_INVALID_EDGE);
mEdges[island.mLastEdge[edge.mEdgeType]].mNextIslandEdge = edgeIndex;
}
else
{
PX_ASSERT(island.mFirstEdge[edge.mEdgeType] == IG_INVALID_EDGE);
island.mFirstEdge[edge.mEdgeType] = edgeIndex;
}
edge.mPrevIslandEdge = island.mLastEdge[edge.mEdgeType];
island.mLastEdge[edge.mEdgeType] = edgeIndex;
island.mEdgeCount[edge.mEdgeType]++;
}
PX_FORCE_INLINE void removeNodeFromIsland(Island& island, NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
if(node.mNextNode.isValid())
{
PX_ASSERT(mNodes[node.mNextNode.index()].mPrevNode.index() == nodeIndex.index());
mNodes[node.mNextNode.index()].mPrevNode = node.mPrevNode;
}
else
{
PX_ASSERT(island.mLastNode.index() == nodeIndex.index());
island.mLastNode = node.mPrevNode;
}
if(node.mPrevNode.isValid())
{
PX_ASSERT(mNodes[node.mPrevNode.index()].mNextNode.index() == nodeIndex.index());
mNodes[node.mPrevNode.index()].mNextNode = node.mNextNode;
}
else
{
PX_ASSERT(island.mRootNode.index() == nodeIndex.index());
island.mRootNode = node.mNextNode;
}
island.mSize[node.mType]--;
node.mNextNode = NodeIndex(); node.mPrevNode = NodeIndex();
}
//void setEdgeConnectedInternal(EdgeIndex edgeIndex);
//void setEdgeDisconnectedInternal(EdgeIndex edgeIndex);
friend class SimpleIslandManager;
friend class ThirdPassTask;
};
}
struct PartitionIndexData
{
PxU16 mPartitionIndex; //! The current partition this edge is in. Used to find the edge efficiently. PxU8 is probably too small (256 partitions max) but PxU16 should be more than enough
PxU8 mPatchIndex; //! The patch index for this partition edge. There may be multiple entries for a given edge if there are multiple patches.
PxU8 mCType; //! The type of constraint this is
PxU32 mPartitionEntryIndex; //! index of partition edges for this partition
};
struct PartitionNodeData
{
IG::NodeIndex mNodeIndex0;
IG::NodeIndex mNodeIndex1;
PxU32 mNextIndex0;
PxU32 mNextIndex1;
};
#define INVALID_PARTITION_INDEX 0xFFFF
struct PartitionEdge
{
IG::EdgeIndex mEdgeIndex; //! The edge index into the island manager. Used to identify the contact manager/constraint
IG::NodeIndex mNode0; //! The node index for node 0. Can be obtained from the edge index alternatively
IG::NodeIndex mNode1; //! The node idnex for node 1. Can be obtained from the edge index alternatively
bool mInfiniteMass0; //! Whether body 0 is kinematic
bool mArticulation0; //! Whether body 0 is an articulation link
bool mInfiniteMass1; //! Whether body 1 is kinematic
bool mArticulation1; //! Whether body 1 is an articulation link
PartitionEdge* mNextPatch; //! for the contact manager has more than 1 patch, we have next patch's edge and previous patch's edge to connect to this edge
PxU32 mUniqueIndex; //! a unique ID for this edge
//KS - This constructor explicitly does not set mUniqueIndex. It is filled in by the pool allocator and this constructor
//is called afterwards. We do not want to stomp the uniqueIndex value
PartitionEdge() : mEdgeIndex(IG_INVALID_EDGE), mInfiniteMass0(false), mArticulation0(false),
mInfiniteMass1(false), mArticulation1(false), mNextPatch(NULL)//, mUniqueIndex(IG_INVALID_EDGE)
{
}
};
}
#endif

View File

@ -0,0 +1,48 @@
//
// 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-2021 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 PXS_KERNEL_WRANGLER_H
#define PXS_KERNEL_WRANGLER_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
class KernelWrangler;
class PxErrorCallback;
class PxsKernelWranglerManager
{
public:
virtual ~PxsKernelWranglerManager(){}
virtual KernelWrangler* getKernelWrangler() = 0;
};
}
#endif

View File

@ -0,0 +1,143 @@
//
// 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-2021 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 PXS_MATERIALCOMBINER_H
#define PXS_MATERIALCOMBINER_H
#include "PxsMaterialCore.h"
namespace physx
{
class PxsMaterialCombiner
{
public:
class PxsCombinedMaterial
{
public:
PxReal staFriction;
PxReal dynFriction;
PxU32 flags; //PxMaterialFlag::eDISABLE_FRICTION, PxMaterialFlag::eDISABLE_STRONG_FRICTION.
};
static PxReal combineRestitution(const PxsMaterialData& material0, const PxsMaterialData& material1);
PxsMaterialCombiner(PxReal staticFrictionScaling, PxReal dynamicFrictionScaling);
PxsCombinedMaterial combineIsotropicFriction(const PxsMaterialData& material0, const PxsMaterialData& material1);
//ML:: move this function to header file to avoid LHS in Xbox
PX_FORCE_INLINE void combineIsotropicFriction(const PxsMaterialData& mat0, const PxsMaterialData& mat1, PxReal& dynamicFriction, PxReal& staticFriction, PxU32& flags)
{
const PxU32 combineFlags= (mat0.flags | mat1.flags); //& (PxMaterialFlag::eDISABLE_STRONG_FRICTION|PxMaterialFlag::eDISABLE_FRICTION); //eventually set DisStrongFric flag, lower all others.
if (!(combineFlags & PxMaterialFlag::eDISABLE_FRICTION))
{
const PxI32 fictionCombineMode = PxMax(mat0.getFrictionCombineMode(), mat1.getFrictionCombineMode());
PxReal dynFriction = 0.f;
PxReal staFriction = 0.f;
switch (fictionCombineMode)
{
case PxCombineMode::eAVERAGE:
dynFriction = 0.5f * (mat0.dynamicFriction + mat1.dynamicFriction);
staFriction = 0.5f * (mat0.staticFriction + mat1.staticFriction);
break;
case PxCombineMode::eMIN:
dynFriction = PxMin(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMin(mat0.staticFriction, mat1.staticFriction);
break;
case PxCombineMode::eMULTIPLY:
dynFriction = (mat0.dynamicFriction * mat1.dynamicFriction);
staFriction = (mat0.staticFriction * mat1.staticFriction);
break;
case PxCombineMode::eMAX:
dynFriction = PxMax(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMax(mat0.staticFriction, mat1.staticFriction);
break;
}
dynFriction*=mDynamicFrictionScaling;
staFriction*=mStaticFrictionScaling;
//isotropic case
const PxReal fDynFriction = PxMax(dynFriction, 0.f);
const PxReal fStaFriction = physx::intrinsics::fsel(staFriction - fDynFriction, staFriction*mStaticFrictionScaling, fDynFriction);
/*dest.dynFriction = fDynFriction;
dest.staFriction = fStaFriction;*/
dynamicFriction = fDynFriction;
staticFriction = fStaFriction;
flags = combineFlags;
}
else
{
/* dest.flags |= PxMaterialFlag::eDISABLE_STRONG_FRICTION;
dest.staFriction = 0.0f;
dest.dynFriction = 0.0f;*/
flags = (combineFlags | PxMaterialFlag::eDISABLE_STRONG_FRICTION);
dynamicFriction = 0.f;
staticFriction = 0.f;
}
}
//private:
protected:
static PX_FORCE_INLINE PxReal combineScalars(PxReal a, PxReal b, PxI32 nxCombineMode)
{
switch (nxCombineMode)
{
case PxCombineMode::eAVERAGE:
return 0.5f * (a + b);
case PxCombineMode::eMIN:
return PxMin(a,b);
case PxCombineMode::eMULTIPLY:
return a * b;
case PxCombineMode::eMAX:
return PxMax(a,b);
default:
/* Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
"Sc::MaterialCombiner::combineScalars(): unknown combine mode");*/
return PxReal(0);
}
}
PxReal mStaticFrictionScaling, mDynamicFrictionScaling;
};
}
#endif

View File

@ -0,0 +1,59 @@
//
// 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-2021 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 PXS_MEMORY_MANAGER_H
#define PXS_MEMORY_MANAGER_H
#include "foundation/PxPreprocessor.h"
#include "foundation/PxSimpleTypes.h"
#include "CmPhysXCommon.h"
namespace physx
{
namespace shdfnd
{
class VirtualAllocatorCallback;
}
class PxsMemoryManager
{
public:
virtual ~PxsMemoryManager(){}
virtual Ps::VirtualAllocatorCallback* createHostMemoryAllocator(const PxU32 gpuComputeVersion = 0) = 0;
virtual Ps::VirtualAllocatorCallback* createDeviceMemoryAllocator(const PxU32 gpuComputeVersion = 0) = 0;
virtual void destroyMemoryAllocator() = 0;
};
PxsMemoryManager* createMemoryManager();
}
#endif

View File

@ -0,0 +1,148 @@
//
// 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-2021 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 PXS_NPHASE_IMPLEMENTATION_CONTEXT_H
#define PXS_NPHASE_IMPLEMENTATION_CONTEXT_H
#include "PxvNphaseImplementationContext.h"
#include "PxsContactManagerState.h"
#include "PxcNpCache.h"
namespace physx
{
struct PxsContactManagers : PxsContactManagerBase
{
Ps::Array<PxsContactManagerOutput> mOutputContactManagers;
Ps::Array<PxsContactManager*> mContactManagerMapping;
Ps::Array<Gu::Cache> mCaches;
PxsContactManagers(const PxU32 bucketId) : PxsContactManagerBase(bucketId),
mOutputContactManagers(PX_DEBUG_EXP("mOutputContactManagers")),
mContactManagerMapping(PX_DEBUG_EXP("mContactManagerMapping")),
mCaches(PX_DEBUG_EXP("mCaches"))
{
}
void clear()
{
mOutputContactManagers.forceSize_Unsafe(0);
mContactManagerMapping.forceSize_Unsafe(0);
mCaches.forceSize_Unsafe(0);
}
private:
PX_NOCOPY(PxsContactManagers)
};
class PxsNphaseImplementationContext: public PxvNphaseImplementationContextUsableAsFallback
{
public:
static PxsNphaseImplementationContext* create(PxsContext& context, IG::IslandSim* islandSim);
PxsNphaseImplementationContext(PxsContext& context, IG::IslandSim* islandSim, PxU32 index = 0): PxvNphaseImplementationContextUsableAsFallback(context), mNarrowPhasePairs(index), mNewNarrowPhasePairs(index),
mModifyCallback(NULL), mIslandSim(islandSim) {}
virtual void destroy();
virtual void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation);
virtual void postBroadPhaseUpdateContactManager() {}
virtual void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation);
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 numPatches);
virtual void registerContactManagers(PxsContactManager** cm, PxU32 nbContactManagers, PxU32 maxContactManagerId);
virtual void unregisterContactManager(PxsContactManager* cm);
virtual void unregisterContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs);
virtual void refreshContactManager(PxsContactManager* cm);
virtual void refreshContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs);
virtual void registerShape(const PxsShapeCore& shapeCore);
virtual void updateShapeMaterial(const PxsShapeCore& shapeCore);
virtual void updateShapeContactOffset(const PxsShapeCore& shapeCore);
virtual void unregisterShape(const PxsShapeCore& shapeCore);
virtual void registerMaterial(const PxsMaterialCore& materialCore);
virtual void updateMaterial(const PxsMaterialCore& materialCore);
virtual void unregisterMaterial(const PxsMaterialCore& materialCore);
virtual void appendContactManagers();
virtual void appendContactManagersFallback(PxsContactManagerOutput* cmOutputs);
virtual void removeContactManagersFallback(PxsContactManagerOutput* cmOutputs);
virtual void setContactModifyCallback(PxContactModifyCallback* callback) { mModifyCallback = callback; }
virtual PxsContactManagerOutputIterator getContactManagerOutputs();
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 npIndex);
virtual PxsContactManagerOutput* getGPUContactManagerOutputBase() { return NULL; }
virtual void acquireContext(){}
virtual void releaseContext(){}
virtual void preallocateNewBuffers(PxU32 /*nbNewPairs*/, PxU32 /*maxIndex*/) { /*TODO - implement if it's useful to do so*/}
void processContactManager(PxReal dt, PxsContactManagerOutput* cmOutputs, PxBaseTask* continuation);
void processContactManagerSecondPass(PxReal dt, PxBaseTask* continuation);
void fetchUpdateContactManager() {}
void startNarrowPhaseTasks() {}
virtual void lock() { mContactManagerMutex.lock(); }
virtual void unlock() { mContactManagerMutex.unlock(); }
Ps::Array<PxU32> mRemovedContactManagers;
PxsContactManagers mNarrowPhasePairs;
PxsContactManagers mNewNarrowPhasePairs;
PxContactModifyCallback* mModifyCallback;
IG::IslandSim* mIslandSim;
Ps::Mutex mContactManagerMutex;
private:
void unregisterContactManagerInternal(PxU32 npIndex, PxsContactManagers& managers, PxsContactManagerOutput* cmOutputs);
PX_NOCOPY(PxsNphaseImplementationContext)
};
}
#endif

View File

@ -0,0 +1,182 @@
//
// 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-2021 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 PXS_RIGID_BODY_H
#define PXS_RIGID_BODY_H
#include "PxvDynamics.h"
#include "CmSpatialVector.h"
namespace physx
{
struct PxsCCDBody;
#define PX_INTERNAL_LOCK_FLAG_START 8
PX_ALIGN_PREFIX(16)
class PxsRigidBody
{
public:
enum PxsRigidBodyFlag
{
eFROZEN = 1 << 0, //This flag indicates that the stabilization is enabled and the body is
//"frozen". By "frozen", we mean that the body's transform is unchanged
//from the previous frame. This permits various optimizations.
eFREEZE_THIS_FRAME = 1 << 1,
eUNFREEZE_THIS_FRAME = 1 << 2,
eACTIVATE_THIS_FRAME = 1 << 3,
eDEACTIVATE_THIS_FRAME = 1 << 4,
// PT: this flag is now only used on the GPU. For the CPU the data is now stored directly in PxsBodyCore.
eDISABLE_GRAVITY_GPU = 1 << 5,
eSPECULATIVE_CCD = 1 << 6,
//KS - copied here for GPU simulation to avoid needing to pass another set of flags around.
eLOCK_LINEAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START),
eLOCK_LINEAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 1),
eLOCK_LINEAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 2),
eLOCK_ANGULAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START + 3),
eLOCK_ANGULAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 4),
eLOCK_ANGULAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 5)
};
PX_FORCE_INLINE PxsRigidBody(PxsBodyCore* core, PxReal freeze_count) :
// PT: TODO: unify naming conventions
mLastTransform (core->body2World),
mInternalFlags (0),
solverIterationCounts (core->solverIterationCounts),
mCCD (NULL),
mCore (core),
sleepLinVelAcc (PxVec3(0.0f)),
freezeCount (freeze_count),
sleepAngVelAcc (PxVec3(0.0f)),
accelScale (1.0f)
{}
PX_FORCE_INLINE ~PxsRigidBody() {}
PX_FORCE_INLINE const PxTransform& getPose() const { PX_ASSERT(mCore->body2World.isSane()); return mCore->body2World; }
PX_FORCE_INLINE const PxVec3& getLinearVelocity() const { PX_ASSERT(mCore->linearVelocity.isFinite()); return mCore->linearVelocity; }
PX_FORCE_INLINE const PxVec3& getAngularVelocity() const { PX_ASSERT(mCore->angularVelocity.isFinite()); return mCore->angularVelocity; }
PX_FORCE_INLINE void setVelocity(const PxVec3& linear,
const PxVec3& angular) { PX_ASSERT(linear.isFinite()); PX_ASSERT(angular.isFinite());
mCore->linearVelocity = linear;
mCore->angularVelocity = angular; }
PX_FORCE_INLINE void setLinearVelocity(const PxVec3& linear) { PX_ASSERT(linear.isFinite()); mCore->linearVelocity = linear; }
PX_FORCE_INLINE void setAngularVelocity(const PxVec3& angular) { PX_ASSERT(angular.isFinite()); mCore->angularVelocity = angular; }
PX_FORCE_INLINE void constrainLinearVelocity();
PX_FORCE_INLINE void constrainAngularVelocity();
PX_FORCE_INLINE PxU32 getIterationCounts() { return mCore->solverIterationCounts; }
PX_FORCE_INLINE PxReal getReportThreshold() const { return mCore->contactReportThreshold; }
PX_FORCE_INLINE const PxTransform& getLastCCDTransform() const { return mLastTransform; }
PX_FORCE_INLINE void saveLastCCDTransform() { mLastTransform = mCore->body2World; }
PX_FORCE_INLINE bool isKinematic() const { return mCore->inverseMass == 0.0f; }
PX_FORCE_INLINE void setPose(const PxTransform& pose) { mCore->body2World = pose; }
PX_FORCE_INLINE void setPosition(const PxVec3& position) { mCore->body2World.p = position; }
PX_FORCE_INLINE PxReal getInvMass() const { return mCore->inverseMass; }
PX_FORCE_INLINE PxVec3 getInvInertia() const { return mCore->inverseInertia; }
PX_FORCE_INLINE PxReal getMass() const { return 1.0f/mCore->inverseMass; }
PX_FORCE_INLINE PxVec3 getInertia() const { return PxVec3(1.0f/mCore->inverseInertia.x,
1.0f/mCore->inverseInertia.y,
1.0f/mCore->inverseInertia.z); }
PX_FORCE_INLINE PxsBodyCore& getCore() { return *mCore; }
PX_FORCE_INLINE const PxsBodyCore& getCore() const { return *mCore; }
PX_FORCE_INLINE PxU32 isActivateThisFrame() const { return PxU32(mInternalFlags & eACTIVATE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isDeactivateThisFrame() const { return PxU32(mInternalFlags & eDEACTIVATE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isFreezeThisFrame() const { return PxU32(mInternalFlags & eFREEZE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isUnfreezeThisFrame() const { return PxU32(mInternalFlags & eUNFREEZE_THIS_FRAME); }
PX_FORCE_INLINE void clearFreezeFlag() { mInternalFlags &= ~eFREEZE_THIS_FRAME; }
PX_FORCE_INLINE void clearUnfreezeFlag() { mInternalFlags &= ~eUNFREEZE_THIS_FRAME; }
PX_FORCE_INLINE void clearAllFrameFlags() { mInternalFlags &= eFROZEN; }
// PT: implemented in PxsCCD.cpp:
void advanceToToi(PxReal toi, PxReal dt, bool clip);
void advancePrevPoseToToi(PxReal toi);
// PxTransform getAdvancedTransform(PxReal toi) const;
Cm::SpatialVector getPreSolverVelocities() const;
PxTransform mLastTransform; //28 (28)
PxU16 mInternalFlags; //30 (30)
PxU16 solverIterationCounts; //32 (32)
PxsCCDBody* mCCD; //36 (40) // only valid during CCD
PxsBodyCore* mCore; //40 (48)
#if !PX_P64_FAMILY
PxU32 alignmentPad[2]; //48 (48)
#endif
PxVec3 sleepLinVelAcc; //60 (60)
PxReal freezeCount; //64 (64)
PxVec3 sleepAngVelAcc; //76 (76)
PxReal accelScale; //80 (80)
}
PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxsRigidBody) & 0x0f));
void PxsRigidBody::constrainLinearVelocity()
{
const PxU32 lockFlags = mCore->lockFlags;
if(lockFlags)
{
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_X)
mCore->linearVelocity.x = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Y)
mCore->linearVelocity.y = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Z)
mCore->linearVelocity.z = 0.0f;
}
}
void PxsRigidBody::constrainAngularVelocity()
{
const PxU32 lockFlags = mCore->lockFlags;
if(lockFlags)
{
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_X)
mCore->angularVelocity.x = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y)
mCore->angularVelocity.y = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)
mCore->angularVelocity.z = 0.0f;
}
}
}
#endif

View File

@ -0,0 +1,54 @@
//
// 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-2021 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 PXS_SHAPESIM_H
#define PXS_SHAPESIM_H
#include "PxsBodySim.h"
#include "PxsIslandNodeIndex.h"
namespace physx
{
struct PxsShapeCore;
//PxsBodySim is 12 or 16 bytes
struct PxsShapeSim// : public PxsBodySim
{
PxsShapeCore* mShapeCore; // 4 or 8
IG::NodeIndex mBodySimIndex; // 8 or 12
PxU32 mElementIndex; // 12 or 16 transform cache and bound index
PxU32 mShapeIndex; // 16 or 20
#if PX_P64_FAMILY
PxU32 mPad[3];
#endif
};
}//physx
#endif

View File

@ -0,0 +1,202 @@
//
// 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-2021 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 PXS_SIMPLE_ISLAND_GEN_H
#define PXS_SIMPLE_ISLAND_GEN_H
#include "PxsIslandSim.h"
#include "CmTask.h"
namespace physx
{
namespace Sc
{
class Interaction;
}
namespace IG
{
class SimpleIslandManager;
class ThirdPassTask : public Cm::Task
{
SimpleIslandManager& mIslandManager;
IslandSim& mIslandSim;
public:
ThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager, IslandSim& islandSim);
virtual void runInternal();
virtual const char* getName() const
{
return "ThirdPassIslandGenTask";
}
private:
PX_NOCOPY(ThirdPassTask)
};
class PostThirdPassTask : public Cm::Task
{
SimpleIslandManager& mIslandManager;
public:
PostThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager);
virtual void runInternal();
virtual const char* getName() const
{
return "PostThirdPassTask";
}
private:
PX_NOCOPY(PostThirdPassTask)
};
class SimpleIslandManager
{
HandleManager<PxU32> mNodeHandles; //! Handle manager for nodes
HandleManager<EdgeIndex> mEdgeHandles; //! Handle manager for edges
//An array of destroyed nodes
Ps::Array<NodeIndex> mDestroyedNodes;
Cm::BlockArray<Sc::Interaction*> mInteractions;
//Edges destroyed this frame
Ps::Array<EdgeIndex> mDestroyedEdges;
Ps::Array<PartitionEdge*> mFirstPartitionEdges;
Ps::Array<PartitionEdge*> mDestroyedPartitionEdges;
//KS - stores node indices for a given edge. Node index 0 is at 2* edgeId and NodeIndex1 is at 2*edgeId + 1
//can also be used for edgeInstance indexing so there's no need to figure out outboundNode ID either!
Cm::BlockArray<NodeIndex> mEdgeNodeIndices;
Cm::BlockArray<void*> mConstraintOrCm; //! Pointers to either the constraint or Cm for this pair
Cm::BitMap mConnectedMap;
IslandSim mIslandManager;
IslandSim mSpeculativeIslandManager;
ThirdPassTask mSpeculativeThirdPassTask;
ThirdPassTask mAccurateThirdPassTask;
PostThirdPassTask mPostThirdPassTask;
PxU32 mMaxDirtyNodesPerFrame;
PxU64 mContextID;
public:
SimpleIslandManager(bool useEnhancedDeterminism, PxU64 contextID);
~SimpleIslandManager();
NodeIndex addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive);
void removeNode(const NodeIndex index);
NodeIndex addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive);
EdgeIndex addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction);
EdgeIndex addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction);
bool isConnected(EdgeIndex edgeIndex) const { return !!mConnectedMap.test(edgeIndex); }
PX_FORCE_INLINE NodeIndex getEdgeIndex(EdgeInstanceIndex edgeIndex) const { return mEdgeNodeIndices[edgeIndex]; }
void activateNode(NodeIndex index);
void deactivateNode(NodeIndex index);
void putNodeToSleep(NodeIndex index);
void removeConnection(EdgeIndex edgeIndex);
void firstPassIslandGen();
void additionalSpeculativeActivation();
void secondPassIslandGen();
void thirdPassIslandGen(PxBaseTask* continuation);
void clearDestroyedEdges();
void setEdgeConnected(EdgeIndex edgeIndex);
void setEdgeDisconnected(EdgeIndex edgeIndex);
bool getIsEdgeConnected(EdgeIndex edgeIndex);
void setEdgeRigidCM(const EdgeIndex edgeIndex, PxsContactManager* cm);
void clearEdgeRigidCM(const EdgeIndex edgeIndex);
void setKinematic(IG::NodeIndex nodeIndex);
void setDynamic(IG::NodeIndex nodeIndex);
const IslandSim& getSpeculativeIslandSim() const { return mSpeculativeIslandManager; }
const IslandSim& getAccurateIslandSim() const { return mIslandManager; }
IslandSim& getAccurateIslandSim() { return mIslandManager; }
PX_FORCE_INLINE PxU32 getNbEdgeHandles() const { return mEdgeHandles.getTotalHandles(); }
PX_FORCE_INLINE PxU32 getNbNodeHandles() const { return mNodeHandles.getTotalHandles(); }
void deactivateEdge(const EdgeIndex edge);
PX_FORCE_INLINE PxsContactManager* getContactManager(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE PxsContactManager* getContactManagerUnsafe(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Dy::Constraint* getConstraint(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Dy::Constraint* getConstraintUnsafe(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Sc::Interaction* getInteraction(IG::EdgeIndex edgeId) const { return mInteractions[edgeId]; }
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
bool checkInternalConsistency();
private:
friend class ThirdPassTask;
friend class PostThirdPassTask;
bool validateDeactivations() const;
PX_NOCOPY(SimpleIslandManager)
};
}
}
#endif

View File

@ -0,0 +1,144 @@
//
// 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-2021 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 PXS_SIMULATION_CONTROLLER_H
#define PXS_SIMULATION_CONTROLLER_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxPreprocessor.h"
#include "foundation/PxTransform.h"
#include "CmBitMap.h"
#include "PsArray.h"
namespace physx
{
namespace Dy
{
class Context;
struct Constraint;
class ArticulationV;
class FeatherstoneArticulation;
struct ArticulationJointCore;
}
namespace Cm
{
class EventProfiler;
}
namespace Bp
{
class BoundsArray;
class BroadPhase;
}
namespace IG
{
class SimpleIslandManager;
class IslandSim;
class NodeIndex;
}
class PxsTransformCache;
class PxvNphaseImplementationContext;
class PxBaseTask;
struct PxsBodySim;
struct PxsShapeSim;
class PxsRigidBody;
class PxsKernelWranglerManager;
class PxsHeapMemoryAllocatorManager;
template<typename T> class PxgIterator;
struct PxgSolverConstraintManagerConstants;
class PxsSimulationControllerCallback
{
public:
virtual void updateScBodyAndShapeSim(PxBaseTask* continuation) = 0;
virtual PxU32 getNbCcdBodies() = 0;
virtual ~PxsSimulationControllerCallback() {}
};
class PxsSimulationController
{
public:
PxsSimulationController(PxsSimulationControllerCallback* callback): mCallback(callback){}
virtual ~PxsSimulationController(){}
virtual void addJoint(const PxU32 edgeIndex, Dy::Constraint* constraint, IG::IslandSim& islandSim, Ps::Array<PxU32>& jointIndices,
Ps::Array<PxgSolverConstraintManagerConstants, Ps::VirtualAllocator>& managerIter, PxU32 uniqueId) = 0;
virtual void removeJoint(const PxU32 edgeIndex, Dy::Constraint* constraint, Ps::Array<PxU32>& jointIndices, IG::IslandSim& islandSim) = 0;
virtual void addShape(PxsShapeSim* shapeSim, const PxU32 index) = 0;
virtual void removeShape(const PxU32 index) = 0;
virtual void addDynamic(PxsRigidBody* rigidBody, const IG::NodeIndex& nodeIndex) = 0;
virtual void addDynamics(PxsRigidBody** rigidBody, const PxU32* nodeIndex, PxU32 nbToProcess) = 0;
virtual void addArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void releaseArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void releaseDeferredArticulationIds() = 0;
virtual void updateDynamic(const bool isArticulationLink, const IG::NodeIndex&) = 0;
virtual void updateJoint(const PxU32 edgeIndex, Dy::Constraint* constraint) = 0;
virtual void updateBodies(PxsRigidBody** rigidBodies, PxU32* nodeIndices, const PxU32 nbBodies) = 0;
virtual void updateBodiesAndShapes(PxBaseTask* continuation) = 0;
virtual void update(const PxU32 bitMapWordCounts) = 0;
virtual void updateArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void updateArticulationJoint(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void gpuDmabackData(PxsTransformCache& cache, Bp::BoundsArray& boundArray, Cm::BitMapPinned& changedAABBMgrHandles) = 0;
virtual void udpateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) = 0;
virtual PxU32* getActiveBodies() = 0;
virtual PxU32* getDeactiveBodies() = 0;
virtual void** getRigidBodies() = 0;
virtual PxU32 getNbBodies() = 0;
virtual PxU32* getUnfrozenShapes() = 0;
virtual PxU32* getFrozenShapes() = 0;
virtual PxsShapeSim** getShapeSims() = 0;
virtual PxU32 getNbFrozenShapes() = 0;
virtual PxU32 getNbUnfrozenShapes() = 0;
virtual void clear() = 0;
virtual void setBounds(Bp::BoundsArray* boundArray) = 0;
virtual void reserve(const PxU32 nbBodies) = 0;
virtual PxU32 getArticulationRemapIndex(const PxU32 nodeIndex) = 0;
protected:
PxsSimulationControllerCallback* mCallback;
};
PxsSimulationController* createSimulationController(PxsSimulationControllerCallback* callback);
}
#endif

View File

@ -0,0 +1,144 @@
//
// 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-2021 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 PXS_TRANSFORM_CACHE_H
#define PXS_TRANSFORM_CACHE_H
#include "CmPhysXCommon.h"
#include "CmIDPool.h"
#include "CmBitMap.h"
#include "PsUserAllocated.h"
#include "PsAllocator.h"
#define PX_DEFAULT_CACHE_SIZE 512
namespace physx
{
struct PxsTransformFlag
{
enum Flags
{
eFROZEN = (1 << 0)
};
};
struct PX_ALIGN_PREFIX(16) PxsCachedTransform
{
PxTransform transform;
PxU32 flags;
PX_FORCE_INLINE PxU32 isFrozen() const { return flags & PxsTransformFlag::eFROZEN; }
}
PX_ALIGN_SUFFIX(16);
class PxsTransformCache : public Ps::UserAllocated
{
typedef PxU32 RefCountType;
public:
PxsTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback) : mTransformCache(Ps::VirtualAllocator(&allocatorCallback)), mHasAnythingChanged(true)
{
/*mTransformCache.reserve(PX_DEFAULT_CACHE_SIZE);
mTransformCache.forceSize_Unsafe(PX_DEFAULT_CACHE_SIZE);*/
mUsedSize = 0;
}
void initEntry(PxU32 index)
{
PxU32 oldCapacity = mTransformCache.capacity();
if (index >= oldCapacity)
{
PxU32 newCapacity = Ps::nextPowerOfTwo(index);
mTransformCache.reserve(newCapacity);
mTransformCache.forceSize_Unsafe(newCapacity);
}
mUsedSize = PxMax(mUsedSize, index + 1u);
}
PX_FORCE_INLINE void setTransformCache(const PxTransform& transform, const PxU32 flags, const PxU32 index)
{
mTransformCache[index].transform = transform;
mTransformCache[index].flags = flags;
mHasAnythingChanged = true;
}
PX_FORCE_INLINE const PxsCachedTransform& getTransformCache(const PxU32 index) const
{
return mTransformCache[index];
}
PX_FORCE_INLINE PxsCachedTransform& getTransformCache(const PxU32 index)
{
return mTransformCache[index];
}
PX_FORCE_INLINE void shiftTransforms(const PxVec3& shift)
{
for (PxU32 i = 0; i < mTransformCache.capacity(); i++)
{
mTransformCache[i].transform.p += shift;
}
mHasAnythingChanged = true;
}
PX_FORCE_INLINE PxU32 getTotalSize() const
{
return mUsedSize;
}
PX_FORCE_INLINE const PxsCachedTransform* getTransforms() const
{
return mTransformCache.begin();
}
PX_FORCE_INLINE PxsCachedTransform* getTransforms()
{
return mTransformCache.begin();
}
PX_FORCE_INLINE Ps::Array<PxsCachedTransform, Ps::VirtualAllocator>* getCachedTransformArray()
{
return &mTransformCache;
}
PX_FORCE_INLINE void resetChangedState() { mHasAnythingChanged = false; }
PX_FORCE_INLINE void setChangedState() { mHasAnythingChanged = true; }
PX_FORCE_INLINE bool hasChanged() const { return mHasAnythingChanged; }
private:
Ps::Array<PxsCachedTransform, Ps::VirtualAllocator> mTransformCache;
PxU32 mUsedSize;
bool mHasAnythingChanged;
};
}
#endif

View File

@ -0,0 +1,223 @@
//
// 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-2021 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 PXV_NPHASE_IMPLEMENTATION_CONTEXT_H
#define PXV_NPHASE_IMPLEMENTATION_CONTEXT_H
#include "PxSceneDesc.h"
#include "PxsContactManagerState.h"
#include "PsArray.h"
namespace physx
{
namespace IG
{
class SimpleIslandManager;
class IslandSim;
typedef PxU32 EdgeIndex;
}
namespace Dy
{
class Context;
}
class PxBaseTask;
class PxsContext;
struct PxsShapeCore;
class PxsMaterialCore;
struct PxgDynamicsMemoryConfig;
class PxsContactManager;
struct PxsContactManagerOutput;
class PxsKernelWranglerManager;
class PxsHeapMemoryAllocatorManager;
struct PxsContactManagerBase
{
static const PxU32 NEW_CONTACT_MANAGER_MASK = 0x80000000;
static const PxU32 GPU_NP_OFFSET = 0x4;
static const PxU32 MaxBucketBits = 3;
const PxU32 mBucketId;
PxsContactManagerBase(const PxU32 bucketId) : mBucketId(bucketId)
{
PX_ASSERT(bucketId < (1<<MaxBucketBits));
}
PX_FORCE_INLINE PxU32 computeId(const PxU32 index) const { PX_ASSERT(index < PxU32(1 << (32 - (MaxBucketBits-1)))); return (index << MaxBucketBits) | (mBucketId); }
static PX_FORCE_INLINE PxU32 computeIndexFromId(const PxU32 id) { return id >> MaxBucketBits; }
static PX_FORCE_INLINE PxU32 computeBucketIndexFromId(const PxU32 id) { return id & ((1<<MaxBucketBits)-1); }
private:
PX_NOCOPY(PxsContactManagerBase)
};
class PxsContactManagerOutputIterator
{
PxU32 mOffsets[1<<PxsContactManagerBase::MaxBucketBits];
PxsContactManagerOutput* mOutputs;
public:
PxsContactManagerOutputIterator() : mOutputs(NULL)
{
}
PxsContactManagerOutputIterator(PxU32* offsets, PxU32 nbOffsets, PxsContactManagerOutput* outputs) : mOutputs(outputs)
{
PX_ASSERT(nbOffsets <= (1<<PxsContactManagerBase::MaxBucketBits));
for(PxU32 a = 0; a < nbOffsets; ++a)
{
mOffsets[a] = offsets[a];
}
}
PX_FORCE_INLINE PxsContactManagerOutput& getContactManager(PxU32 id)
{
PX_ASSERT((id & PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK) == 0);
PxU32 bucketId = PxsContactManagerBase::computeBucketIndexFromId(id);
PxU32 cmOutId = PxsContactManagerBase::computeIndexFromId(id);
return mOutputs[mOffsets[bucketId] + cmOutId];
}
PxU32 getIndex(PxU32 id)
{
PX_ASSERT((id & PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK) == 0);
PxU32 bucketId = PxsContactManagerBase::computeBucketIndexFromId(id);
PxU32 cmOutId = PxsContactManagerBase::computeIndexFromId(id);
return mOffsets[bucketId] + cmOutId;
}
};
class PxvNphaseImplementationContext
{
private:
PX_NOCOPY(PxvNphaseImplementationContext)
public:
PxvNphaseImplementationContext(PxsContext& context): mContext(context) {}
virtual ~PxvNphaseImplementationContext() {}
virtual void destroy() = 0;
virtual void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation) = 0;
virtual void postBroadPhaseUpdateContactManager() = 0;
virtual void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation) = 0;
virtual void fetchUpdateContactManager() = 0;
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 patchCount) = 0;
virtual void registerContactManagers(PxsContactManager** cm, PxU32 nbContactManagers, PxU32 maxContactManagerId) = 0;
virtual void unregisterContactManager(PxsContactManager* cm) = 0;
virtual void refreshContactManager(PxsContactManager* cm) = 0;
virtual void registerShape(const PxsShapeCore& shapeCore) = 0;
virtual void unregisterShape(const PxsShapeCore& shapeCore) = 0;
virtual void registerMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void updateMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void unregisterMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void updateShapeMaterial(const PxsShapeCore& shapeCore) = 0;
virtual PxsContactManagerOutput* getGPUContactManagerOutputBase() = 0;
virtual void startNarrowPhaseTasks() = 0;
virtual void appendContactManagers() = 0;
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 index) = 0;
virtual PxsContactManagerOutputIterator getContactManagerOutputs() = 0;
virtual void setContactModifyCallback(PxContactModifyCallback* callback) = 0;
virtual void acquireContext() = 0;
virtual void releaseContext() = 0;
virtual void preallocateNewBuffers(PxU32 nbNewPairs, PxU32 maxIndex) = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
protected:
PxsContext& mContext;
};
class PxvNphaseImplementationFallback
{
private:
PX_NOCOPY(PxvNphaseImplementationFallback)
public:
PxvNphaseImplementationFallback() {}
virtual ~PxvNphaseImplementationFallback() {}
virtual void processContactManager(PxReal dt, PxsContactManagerOutput* cmOutputs, PxBaseTask* continuation) = 0;
virtual void processContactManagerSecondPass(PxReal dt, PxBaseTask* continuation) = 0;
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 numPatches) = 0;
virtual void unregisterContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs) = 0;
virtual void refreshContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs) = 0;
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 npId) = 0;
virtual void appendContactManagersFallback(PxsContactManagerOutput* outputs) = 0;
virtual void setContactModifyCallback(PxContactModifyCallback* callback) = 0;
virtual void removeContactManagersFallback(PxsContactManagerOutput* cmOutputs) = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
};
class PxvNphaseImplementationContextUsableAsFallback: public PxvNphaseImplementationContext, public PxvNphaseImplementationFallback
{
private:
PX_NOCOPY(PxvNphaseImplementationContextUsableAsFallback)
public:
PxvNphaseImplementationContextUsableAsFallback(PxsContext& context): PxvNphaseImplementationContext(context) {}
virtual ~PxvNphaseImplementationContextUsableAsFallback() {}
};
PxvNphaseImplementationContextUsableAsFallback* createNphaseImplementationContext(PxsContext& context, IG::IslandSim* islandSim);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxsContactManager.h"
#include "PxsRigidBody.h"
#include "PxcContactMethodImpl.h"
#include "PxvManager.h"
#include "PxsIslandSim.h"
using namespace physx;
PxsContactManager::PxsContactManager(PxsContext*, PxU32 index) /*:
mUserData (NULL)*/
{
mFlags = 0;
// PT: TODO: any reason why we don't initialize all members here, e.g. shapeCore pointers?
mNpUnit.index = index;
mNpUnit.rigidCore0 = NULL;
mNpUnit.rigidCore1 = NULL;
mNpUnit.restDistance = 0;
mNpUnit.dominance0 = 1u;
mNpUnit.dominance1 = 1u;
mNpUnit.frictionDataPtr = NULL;
mNpUnit.frictionPatchCount = 0;
}
PxsContactManager::~PxsContactManager()
{
}
void PxsContactManager::setCCD(bool enable)
{
PxU32 flags = mFlags & (~PXS_CM_CCD_CONTACT);
if (enable)
flags |= PXS_CM_CCD_LINEAR;
else
flags &= ~PXS_CM_CCD_LINEAR;
mFlags = flags;
}
void PxsContactManager::resetCachedState()
{
// happens when the body transform or shape relative transform changes.
PxcNpWorkUnitClearCachedState(mNpUnit);
}
void PxsContactManager::resetFrictionCachedState()
{
// happens when the body transform or shape relative transform changes.
PxcNpWorkUnitClearFrictionCachedState(mNpUnit);
}

View File

@ -0,0 +1,623 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxProfileZone.h"
#include "PxvConfig.h"
#include "PxcContactCache.h"
#include "PxsRigidBody.h"
#include "PxsContactManager.h"
#include "PxsContext.h"
#include "PxPhysXConfig.h"
#include "CmBitMap.h"
#include "CmFlushPool.h"
#include "PxsMaterialManager.h"
#include "PxSceneDesc.h"
#include "PxsCCD.h"
#include "PxvGeometry.h"
#include "PxvManager.h"
#include "PxsSimpleIslandManager.h"
#if PX_SUPPORT_GPU_PHYSX
#include "PxPhysXGpu.h"
#endif
#include "PxcNpContactPrepShared.h"
#include "PxcNpCache.h"
using namespace physx;
using namespace physx::shdfnd;
#define PXS_CONTACTMANAGER_SLABSIZE 1024
#define PXS_MAX_CONTACTMANAGER_SLABS 64
#define PXS_BODYSHAPE_SLABSIZE 1024
#define PXS_MAX_BODYSHAPE_SLABS 16
PxsContext::PxsContext(const PxSceneDesc& desc, PxTaskManager* taskManager, Cm::FlushPool& taskPool, PxCudaContextManager* cudaContextManager, PxU64 contextID) :
mNpThreadContextPool (this),
mContactManagerPool ("mContactManagerPool", this, 256),
mManifoldPool ("mManifoldPool", 256),
mSphereManifoldPool ("mSphereManifoldPool", 256),
mContactModifyCallback (NULL),
mNpImplementationContext (NULL),
mNpFallbackImplementationContext(NULL),
mTaskManager (taskManager),
mTaskPool (taskPool),
mCudaContextManager (cudaContextManager),
mPCM (desc.flags & PxSceneFlag::eENABLE_PCM),
mContactCache (false),
mCreateAveragePoint (desc.flags & PxSceneFlag::eENABLE_AVERAGE_POINT),
mContextID (contextID)
{
clearManagerTouchEvents();
mVisualizationCullingBox.setMaximal();
PxMemZero(mVisualizationParams, sizeof(PxReal) * PxVisualizationParameter::eNUM_VALUES);
mNpMemBlockPool.init(desc.nbContactDataBlocks, desc.maxNbContactDataBlocks);
}
PxsContext::~PxsContext()
{
if(mTransformCache)
{
mTransformCache->~PxsTransformCache();
PX_FREE(mTransformCache);
}
mTransformCache = NULL;
mContactManagerPool.destroy(); //manually destroy the contact manager pool, otherwise pool deletion order is random and we can get into trouble with references into other pools needed during destruction.
}
// =========================== Create methods
namespace physx
{
bool gEnablePCMCaching[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT] =
{
//eSPHERE,
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//ePLANE
{
false, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
},
//eCAPSULE,
{
false, //eSPHERE
true, //ePLANE
false, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eBOX,
{
false, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eCONVEXMESH,
{
true, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eTRIANGLEMESH,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
},
//eHEIGHTFIELD,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
}
};
}
void PxsContext::createTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback)
{
mTransformCache = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsTransformCache), PX_DEBUG_EXP("PxsTransformCache")), PxsTransformCache(allocatorCallback));
}
PxsContactManager* PxsContext::createContactManager(PxsContactManager* contactManager, const bool useCCD)
{
PxsContactManager* cm = contactManager? contactManager : mContactManagerPool.get();
if(cm)
{
PxcNpWorkUnitClearContactState(cm->getWorkUnit());
PxcNpWorkUnitClearCachedState(cm->getWorkUnit());
if (contactManager == NULL)
{
if (cm->getIndex() >= mActiveContactManager.size())
{
PxU32 newSize = (2 * cm->getIndex() + 256)&~255;
mActiveContactManager.resize(newSize);
}
mActiveContactManager.set(cm->getIndex());
if (useCCD)
{
if (cm->getIndex() >= mActiveContactManagersWithCCD.size())
{
PxU32 newSize = (2 * cm->getIndex() + 256)&~255;
mActiveContactManagersWithCCD.resize(newSize);
}
mActiveContactManagersWithCCD.set(cm->getIndex());
}
}
}
else
{
PX_WARN_ONCE("Reached limit of contact pairs.");
}
return cm;
}
void PxsContext::createCache(Gu::Cache& cache, PxsContactManager* cm, PxU8 geomType0, PxU8 geomType1)
{
if(cm)
{
if(mPCM)
{
if(gEnablePCMCaching[geomType0][geomType1])
{
if(geomType0 <= PxGeometryType::eCONVEXMESH &&
geomType1 <= PxGeometryType::eCONVEXMESH)
{
if(geomType0 == PxGeometryType::eSPHERE || geomType1 == PxGeometryType::eSPHERE)
{
Gu::PersistentContactManifold* manifold = mSphereManifoldPool.allocate();
new(manifold) Gu::SpherePersistentContactManifold();
cache.setManifold(manifold);
}
else
{
Gu::PersistentContactManifold* manifold = mManifoldPool.allocate();
new(manifold) Gu::LargePersistentContactManifold();
cache.setManifold(manifold);
}
cache.getManifold().clearManifold();
}
else
{
//ML: raised 1 to indicate the manifold is multiManifold which is for contact gen in mesh/height field
//cache.manifold = 1;
cache.setMultiManifold(NULL);
}
}
else
{
//cache.manifold = 0;
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
}
}
void PxsContext::destroyContactManager(PxsContactManager* cm)
{
const PxU32 idx = cm->getIndex();
if (cm->getCCD())
mActiveContactManagersWithCCD.growAndReset(idx);
mActiveContactManager.growAndReset(idx);
mContactManagerTouchEvent.growAndReset(idx);
mContactManagerPatchChangeEvent.growAndReset(idx);
mContactManagerPool.put(cm);
}
void PxsContext::destroyCache(Gu::Cache& cache)
{
if(cache.isManifold())
{
if(!cache.isMultiManifold())
{
Gu::PersistentContactManifold& manifold = cache.getManifold();
if (manifold.mCapacity == GU_SPHERE_MANIFOLD_CACHE_SIZE)
{
mSphereManifoldPool.deallocate(static_cast<Gu::SpherePersistentContactManifold*>(&manifold));
}
else
{
mManifoldPool.deallocate(static_cast<Gu::LargePersistentContactManifold*>(&manifold));
}
}
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
void PxsContext::setScratchBlock(void* addr, PxU32 size)
{
mScratchAllocator.setBlock(addr, size);
}
void PxsContext::setContactDistance(Ps::Array<PxReal, Ps::VirtualAllocator>* contactDistance)
{
mContactDistance = contactDistance;
}
void PxsContext::shiftOrigin(const PxVec3& shift)
{
// transform cache
mTransformCache->shiftTransforms(-shift);
#if 0
if (getContactCacheFlag())
{
//Iterate all active contact managers
Cm::BitMap::Iterator it(mActiveContactManager);
PxU32 index = it.getNext();
while(index != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
PxcNpWorkUnit& npwUnit = cm->getWorkUnit();
// contact cache
if(!npwUnit.pairCache.isManifold())
{
PxU8* contactCachePtr = npwUnit.pairCache.mCachedData;
if (contactCachePtr)
{
PxcLocalContactsCache* lcc;
PxU8* contacts = PxcNpCacheRead(npwUnit.pairCache, lcc);
#ifdef _DEBUG
PxcLocalContactsCache testCache;
PxU32 testBytes;
const PxU8* testPtr = PxcNpCacheRead2(npwUnit.pairCache, testCache, testBytes);
#endif
lcc->mTransform0.p -= shift;
lcc->mTransform1.p -= shift;
const PxU32 nbContacts = lcc->mNbCachedContacts;
const bool sameNormal = lcc->mSameNormal;
const bool useFaceIndices = lcc->mUseFaceIndices;
for(PxU32 i=0; i < nbContacts; i++)
{
if (i != nbContacts-1)
Ps::prefetchLine(contacts, 128);
if(!i || !sameNormal)
contacts += sizeof(PxVec3);
PxVec3* cachedPoint = reinterpret_cast<PxVec3*>(contacts);
*cachedPoint -= shift;
contacts += sizeof(PxVec3);
contacts += sizeof(PxReal);
if(useFaceIndices)
contacts += 2 * sizeof(PxU32);
}
#ifdef _DEBUG
PX_ASSERT(contacts == (testPtr + testBytes));
#endif
}
}
index = it.getNext();
}
}
#endif
//
// adjust visualization culling box
//
PxBounds3 maximalBounds;
maximalBounds.setMaximal();
if ((mVisualizationCullingBox.minimum != maximalBounds.minimum) || (mVisualizationCullingBox.maximum != maximalBounds.maximum))
{
mVisualizationCullingBox.minimum -= shift;
mVisualizationCullingBox.maximum -= shift;
}
}
void PxsContext::swapStreams()
{
mNpMemBlockPool.swapNpCacheStreams();
}
void PxsContext::mergeCMDiscreteUpdateResults(PxBaseTask* /*continuation*/)
{
PX_PROFILE_ZONE("Sim.narrowPhaseMerge", mContextID);
this->mNpImplementationContext->appendContactManagers();
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
for(PxcNpThreadContext* threadContext = threadContextIt.getNext(); threadContext; threadContext = threadContextIt.getNext())
{
mCMTouchEventCount[PXS_LOST_TOUCH_COUNT] += threadContext->getLocalLostTouchCount();
mCMTouchEventCount[PXS_NEW_TOUCH_COUNT] += threadContext->getLocalNewTouchCount();
mCMTouchEventCount[PXS_PATCH_FOUND_COUNT] += threadContext->getLocalFoundPatchCount();
mCMTouchEventCount[PXS_PATCH_LOST_COUNT] += threadContext->getLocalLostPatchCount();
#if PX_ENABLE_SIM_STATS
for(PxU32 i=0;i<PxGeometryType::eGEOMETRY_COUNT;i++)
{
#if PX_DEBUG
for(PxU32 j=0; j<i; j++)
PX_ASSERT(!threadContext->mDiscreteContactPairs[i][j]);
#endif
for(PxU32 j=i; j<PxGeometryType::eGEOMETRY_COUNT; j++)
{
const PxU32 nb = threadContext->mDiscreteContactPairs[i][j];
const PxU32 nbModified = threadContext->mModifiedContactPairs[i][j];
mSimStats.mNbDiscreteContactPairs[i][j] += nb;
mSimStats.mNbModifiedContactPairs[i][j] += nbModified;
mSimStats.mNbDiscreteContactPairsTotal += nb;
}
}
mSimStats.mNbDiscreteContactPairsWithCacheHits += threadContext->mNbDiscreteContactPairsWithCacheHits;
mSimStats.mNbDiscreteContactPairsWithContacts += threadContext->mNbDiscreteContactPairsWithContacts;
mSimStats.mTotalCompressedContactSize += threadContext->mCompressedCacheSize;
//KS - this data is not available yet
//mSimStats.mTotalConstraintSize += threadContext->mConstraintSize;
threadContext->clearStats();
#endif
mContactManagerTouchEvent.combineInPlace<Cm::BitMap::OR>(threadContext->getLocalChangeTouch());
mContactManagerPatchChangeEvent.combineInPlace<Cm::BitMap::OR>(threadContext->getLocalPatchChangeMap());
mTotalCompressedCacheSize += threadContext->mTotalCompressedCacheSize;
mMaxPatches = PxMax(mMaxPatches, threadContext->mMaxPatches);
threadContext->mTotalCompressedCacheSize = threadContext->mMaxPatches = 0;
}
}
void PxsContext::setCreateContactStream(bool to)
{
mCreateContactStream = to;
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
for(PxcNpThreadContext* threadContext = threadContextIt.getNext(); threadContext; threadContext = threadContextIt.getNext())
{
threadContext->setCreateContactStream(to);
}
}
void PxsContext::updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation)
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->updateContactManager(dt, hasBoundsArrayChanged, hasContactDistanceChanged, continuation, firstPassContinuation);
}
void PxsContext::secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation)
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->secondPassUpdateContactManager(dt, continuation);
}
void PxsContext::fetchUpdateContactManager()
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->fetchUpdateContactManager();
mergeCMDiscreteUpdateResults(NULL);
}
void PxsContext::resetThreadContexts()
{
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
PxcNpThreadContext* threadContext = threadContextIt.getNext();
while(threadContext != NULL)
{
threadContext->reset(mContactManagerTouchEvent.size());
threadContext = threadContextIt.getNext();
}
}
bool PxsContext::getManagerTouchEventCount(int* newTouch, int* lostTouch, int* ccdTouch) const
{
if(newTouch)
*newTouch = int(mCMTouchEventCount[PXS_NEW_TOUCH_COUNT]);
if(lostTouch)
*lostTouch = int(mCMTouchEventCount[PXS_LOST_TOUCH_COUNT]);
if(ccdTouch)
*ccdTouch = int(mCMTouchEventCount[PXS_CCD_RETOUCH_COUNT]);
return true;
}
bool PxsContext::fillManagerTouchEvents(PxvContactManagerTouchEvent* newTouch, PxI32& newTouchCount, PxvContactManagerTouchEvent* lostTouch, PxI32& lostTouchCount,
PxvContactManagerTouchEvent* ccdTouch, PxI32& ccdTouchCount)
{
PxU32 index;
const PxvContactManagerTouchEvent* newTouchStart = newTouch;
const PxvContactManagerTouchEvent* lostTouchStart = lostTouch;
const PxvContactManagerTouchEvent* ccdTouchStart = ccdTouch;
const PxvContactManagerTouchEvent* newTouchEnd = newTouch + newTouchCount;
const PxvContactManagerTouchEvent* lostTouchEnd = lostTouch + lostTouchCount;
const PxvContactManagerTouchEvent* ccdTouchEnd = ccdTouch + ccdTouchCount;
PX_UNUSED(newTouchEnd);
PX_UNUSED(lostTouchEnd);
PX_UNUSED(ccdTouchEnd);
Cm::BitMap::Iterator it(mContactManagerTouchEvent);
while((index = it.getNext()) != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
if(cm->getTouchStatus())
{
if (!cm->getHasCCDRetouch())
{
PX_ASSERT(newTouch < newTouchEnd);
newTouch->manager = cm;
newTouch->userData = cm->getUserData();
newTouch++;
}
else
{
PX_ASSERT(ccdTouch);
PX_ASSERT(ccdTouch < ccdTouchEnd);
ccdTouch->manager = cm;
ccdTouch->userData = cm->getUserData();
cm->clearCCDRetouch();
ccdTouch++;
}
}
else
{
PX_ASSERT(lostTouch < lostTouchEnd);
lostTouch->manager = cm;
lostTouch->userData = cm->getUserData();
lostTouch++;
}
}
newTouchCount = PxI32(newTouch - newTouchStart);
lostTouchCount = PxI32(lostTouch - lostTouchStart);
ccdTouchCount = PxI32(ccdTouch - ccdTouchStart);
return true;
}
bool PxsContext::fillManagerPatchChangedEvents(PxsContactManager** foundPatch, PxU32& foundPatchCount,
PxsContactManager** lostPatch, PxU32& lostPatchCount)
{
Cm::BitMap::Iterator it(mContactManagerPatchChangeEvent);
PxsContactManagerOutputIterator outputs = mNpImplementationContext->getContactManagerOutputs();
PxU32 index;
PxsContactManager** currFoundPatch = foundPatch;
PxsContactManager** currLostPatch = lostPatch;
while((index = it.getNext()) != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
PxcNpWorkUnit& workUnit = cm->getWorkUnit();
PxsContactManagerOutput& output = outputs.getContactManager(workUnit.mNpIndex);
if(output.nbPatches > output.prevPatches)
{
PX_ASSERT(PxU32(currFoundPatch - foundPatch) < foundPatchCount);
*currFoundPatch = cm;
currFoundPatch++;
}
else if(output.nbPatches < output.prevPatches)
{
PX_ASSERT(PxU32(currLostPatch - lostPatch) < lostPatchCount);
*currLostPatch = cm;
currLostPatch++;
}
}
foundPatchCount = PxU32(currFoundPatch - foundPatch);
lostPatchCount = PxU32(currLostPatch - lostPatch);
return true;
}
void PxsContext::beginUpdate()
{
#if PX_ENABLE_SIM_STATS
mSimStats.clearAll();
#endif
}
// Contact manager related
PxReal PxsContext::getVisualizationParameter(PxVisualizationParameter::Enum param) const
{
PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
return mVisualizationParams[param];
}
void PxsContext::setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value)
{
PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
PX_ASSERT(value >= 0.0f);
mVisualizationParams[param] = value;
}

View File

@ -0,0 +1,74 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxsDefaultMemoryManager.h"
namespace physx
{
PxsDefaultMemoryManager::~PxsDefaultMemoryManager()
{
for (PxU32 i = 0; i < mAllocators.size(); ++i)
{
mAllocators[i]->~VirtualAllocatorCallback();
PX_FREE(mAllocators[i]);
}
}
Ps::VirtualAllocatorCallback* PxsDefaultMemoryManager::createHostMemoryAllocator(const PxU32 gpuComputeVersion)
{
PX_UNUSED(gpuComputeVersion);
Ps::VirtualAllocatorCallback* allocator = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsDefaultMemoryAllocator), "PxsDefaultMemoryAllocator"), PxsDefaultMemoryAllocator());
mAllocators.pushBack(allocator);
return allocator;
}
//this is an empty stub
Ps::VirtualAllocatorCallback* PxsDefaultMemoryManager::createDeviceMemoryAllocator(const PxU32 gpuComputeVersion)
{
PX_UNUSED(gpuComputeVersion);
return NULL;
}
void PxsDefaultMemoryManager::destroyMemoryAllocator()
{
for (PxU32 i = 0; i < mAllocators.size(); ++i)
{
mAllocators[i]->~VirtualAllocatorCallback();
PX_FREE(mAllocators[i]);
}
}
PxsMemoryManager* createMemoryManager()
{
return PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsDefaultMemoryManager), PX_DEBUG_EXP("PxsDefaultMemoryManager")), PxsDefaultMemoryManager());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxsMaterialCombiner.h"
#include "PsMathUtils.h"
#include "CmPhysXCommon.h"
#include "PsFoundation.h"
namespace physx
{
PxsMaterialCombiner::PxsMaterialCombiner(PxReal staticFrictionScaling, PxReal dynamicFrictionScaling)
: mStaticFrictionScaling(staticFrictionScaling), mDynamicFrictionScaling(dynamicFrictionScaling)
{}
PxReal PxsMaterialCombiner::combineRestitution(const PxsMaterialData& mat0, const PxsMaterialData& mat1)
{
/*return combineScalars(mat0.restitution, mat1.restitution, PxMax(mat0.restitutionCombineMode, mat1.restitutionCombineMode));*/
return combineScalars(mat0.restitution, mat1.restitution, PxMax(mat0.getRestitutionCombineMode(), mat1.getRestitutionCombineMode()));
}
PxsMaterialCombiner::PxsCombinedMaterial PxsMaterialCombiner::combineIsotropicFriction(const PxsMaterialData& mat0, const PxsMaterialData& mat1)
{
PxsCombinedMaterial dest;
dest.flags = (mat0.flags | mat1.flags); //& (PxMaterialFlag::eDISABLE_STRONG_FRICTION|PxMaterialFlag::eDISABLE_FRICTION); //eventually set DisStrongFric flag, lower all others.
if (!(dest.flags & PxMaterialFlag::eDISABLE_FRICTION))
{
const PxI32 fictionCombineMode = PxMax(mat0.getFrictionCombineMode(), mat1.getFrictionCombineMode());
PxReal dynFriction = 0.f;
PxReal staFriction = 0.f;
switch (fictionCombineMode)
{
case PxCombineMode::eAVERAGE:
dynFriction = 0.5f * (mat0.dynamicFriction + mat1.dynamicFriction);
staFriction = 0.5f * (mat0.staticFriction + mat1.staticFriction);
break;
case PxCombineMode::eMIN:
dynFriction = PxMin(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMin(mat0.staticFriction, mat1.staticFriction);
break;
case PxCombineMode::eMULTIPLY:
dynFriction = (mat0.dynamicFriction * mat1.dynamicFriction);
staFriction = (mat0.staticFriction * mat1.staticFriction);
break;
case PxCombineMode::eMAX:
dynFriction = PxMax(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMax(mat0.staticFriction, mat1.staticFriction);
break;
}
dynFriction*=mDynamicFrictionScaling;
staFriction*=mStaticFrictionScaling;
//isotropic case
const PxReal fDynFriction = PxMax(dynFriction, 0.f);
const PxReal fStaFriction = physx::intrinsics::fsel(staFriction - fDynFriction, staFriction, fDynFriction);
dest.dynFriction = fDynFriction;
dest.staFriction = fStaFriction;
}
else
{
dest.flags |= PxMaterialFlag::eDISABLE_STRONG_FRICTION;
dest.staFriction = 0.0f;
dest.dynFriction = 0.0f;
}
return dest;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,377 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxProfileZone.h"
#include "PxsSimpleIslandManager.h"
#include "PsSort.h"
#include "PxsContactManager.h"
#include "CmTask.h"
#include "DyVArticulation.h"
#define IG_SANITY_CHECKS 0
namespace physx
{
namespace IG
{
ThirdPassTask::ThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager, IslandSim& islandSim) : Cm::Task(contextID), mIslandManager(islandManager), mIslandSim(islandSim)
{
}
PostThirdPassTask::PostThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager) : Cm::Task(contextID), mIslandManager(islandManager)
{
}
SimpleIslandManager::SimpleIslandManager(bool useEnhancedDeterminism, PxU64 contextID) :
mDestroyedNodes (PX_DEBUG_EXP("mDestroyedNodes")),
mDestroyedEdges (PX_DEBUG_EXP("mDestroyedEdges")),
mFirstPartitionEdges (PX_DEBUG_EXP("mFirstPartitionEdges")),
mDestroyedPartitionEdges (PX_DEBUG_EXP("IslandSim::mDestroyedPartitionEdges")),
mIslandManager (&mFirstPartitionEdges, mEdgeNodeIndices, &mDestroyedPartitionEdges, contextID),
mSpeculativeIslandManager (NULL, mEdgeNodeIndices, NULL, contextID),
mSpeculativeThirdPassTask (contextID, *this, mSpeculativeIslandManager),
mAccurateThirdPassTask (contextID, *this, mIslandManager),
mPostThirdPassTask (contextID, *this),
mContextID (contextID)
{
mFirstPartitionEdges.resize(1024);
mMaxDirtyNodesPerFrame = useEnhancedDeterminism ? 0xFFFFFFFF : 1000u;
}
SimpleIslandManager::~SimpleIslandManager()
{
}
NodeIndex SimpleIslandManager::addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive)
{
PxU32 handle = mNodeHandles.getHandle();
NodeIndex nodeIndex(handle);
mIslandManager.addRigidBody(body, isKinematic, isActive, nodeIndex);
mSpeculativeIslandManager.addRigidBody(body, isKinematic, isActive, nodeIndex);
return nodeIndex;
}
void SimpleIslandManager::removeNode(const NodeIndex index)
{
PX_ASSERT(mNodeHandles.isValidHandle(index.index()));
mDestroyedNodes.pushBack(index);
}
NodeIndex SimpleIslandManager::addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive)
{
PxU32 handle = mNodeHandles.getHandle();
NodeIndex nodeIndex(handle);
mIslandManager.addArticulation(articulation, llArtic, isActive, nodeIndex);
mSpeculativeIslandManager.addArticulation(articulation, llArtic, isActive, nodeIndex);
return nodeIndex;
}
EdgeIndex SimpleIslandManager::addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction)
{
EdgeIndex handle = mEdgeHandles.getHandle();
PxU32 nodeIds = 2 * handle;
if (mEdgeNodeIndices.size() == nodeIds)
{
PX_PROFILE_ZONE("ReserveEdges", getContextId());
const PxU32 newSize = nodeIds + 2048;
mEdgeNodeIndices.resize(newSize);
mConstraintOrCm.resize(newSize);
mInteractions.resize(newSize);
}
mEdgeNodeIndices[nodeIds] = nodeHandle1;
mEdgeNodeIndices[nodeIds+1] = nodeHandle2;
mConstraintOrCm[handle] = manager;
mInteractions[handle] = interaction;
mSpeculativeIslandManager.addContactManager(manager, nodeHandle1, nodeHandle2, handle);
if (manager)
manager->getWorkUnit().mEdgeIndex = handle;
if(mConnectedMap.size() == handle)
{
mConnectedMap.resize(2 * (handle + 1));
}
if (mFirstPartitionEdges.capacity() == handle)
{
mFirstPartitionEdges.resize(2 * (handle + 1));
}
mConnectedMap.reset(handle);
return handle;
}
EdgeIndex SimpleIslandManager::addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction)
{
EdgeIndex handle = mEdgeHandles.getHandle();
PxU32 nodeIds = 2 * handle;
if (mEdgeNodeIndices.size() == nodeIds)
{
mEdgeNodeIndices.resize(2 * (mEdgeNodeIndices.size() + 2));
mConstraintOrCm.resize(2 * (handle + 1));
mInteractions.resize(2 * (handle + 1));
}
mEdgeNodeIndices[nodeIds] = nodeHandle1;
mEdgeNodeIndices[nodeIds + 1] = nodeHandle2;
mConstraintOrCm[handle] = constraint;
mInteractions[handle] = interaction;
mIslandManager.addConstraint(constraint, nodeHandle1, nodeHandle2, handle);
mSpeculativeIslandManager.addConstraint(constraint, nodeHandle1, nodeHandle2, handle);
if(mConnectedMap.size() == handle)
{
mConnectedMap.resize(2*(mConnectedMap.size()+1));
}
if (mFirstPartitionEdges.capacity() == handle)
{
mFirstPartitionEdges.resize(2 * (mFirstPartitionEdges.capacity() + 1));
}
mConnectedMap.set(handle);
return handle;
}
void SimpleIslandManager::activateNode(NodeIndex index)
{
mIslandManager.activateNode(index);
mSpeculativeIslandManager.activateNode(index);
}
void SimpleIslandManager::deactivateNode(NodeIndex index)
{
mIslandManager.deactivateNode(index);
mSpeculativeIslandManager.deactivateNode(index);
}
void SimpleIslandManager::putNodeToSleep(NodeIndex index)
{
mIslandManager.putNodeToSleep(index);
mSpeculativeIslandManager.putNodeToSleep(index);
}
void SimpleIslandManager::removeConnection(EdgeIndex edgeIndex)
{
if(edgeIndex == IG_INVALID_EDGE)
return;
mDestroyedEdges.pushBack(edgeIndex);
mSpeculativeIslandManager.removeConnection(edgeIndex);
if(mConnectedMap.test(edgeIndex))
{
mIslandManager.removeConnection(edgeIndex);
mConnectedMap.reset(edgeIndex);
}
mConstraintOrCm[edgeIndex] = NULL;
mInteractions[edgeIndex] = NULL;
}
void SimpleIslandManager::firstPassIslandGen()
{
PX_PROFILE_ZONE("Basic.firstPassIslandGen", getContextId());
mSpeculativeIslandManager.clearDeactivations();
mSpeculativeIslandManager.wakeIslands();
mSpeculativeIslandManager.processNewEdges();
mSpeculativeIslandManager.removeDestroyedEdges();
mSpeculativeIslandManager.processLostEdges(mDestroyedNodes, false, false, mMaxDirtyNodesPerFrame);
}
void SimpleIslandManager::additionalSpeculativeActivation()
{
mSpeculativeIslandManager.wakeIslands2();
}
void SimpleIslandManager::secondPassIslandGen()
{
PX_PROFILE_ZONE("Basic.secondPassIslandGen", getContextId());
mIslandManager.wakeIslands();
mIslandManager.processNewEdges();
mIslandManager.removeDestroyedEdges();
mIslandManager.processLostEdges(mDestroyedNodes, false, false, mMaxDirtyNodesPerFrame);
for(PxU32 a = 0; a < mDestroyedNodes.size(); ++a)
{
mNodeHandles.freeHandle(mDestroyedNodes[a].index());
}
mDestroyedNodes.clear();
//mDestroyedEdges.clear();
}
bool SimpleIslandManager::validateDeactivations() const
{
//This method sanity checks the deactivations produced by third-pass island gen. Specifically, it ensures that any bodies that
//the speculative IG wants to deactivate are also candidates for deactivation in the accurate island gen. In practice, both should be the case. If this fails, something went wrong...
const NodeIndex* const nodeIndices = mSpeculativeIslandManager.getNodesToDeactivate(Node::eRIGID_BODY_TYPE);
const PxU32 nbNodesToDeactivate = mSpeculativeIslandManager.getNbNodesToDeactivate(Node::eRIGID_BODY_TYPE);
for(PxU32 i = 0; i < nbNodesToDeactivate; ++i)
{
//Node is active in accurate sim => mismatch between accurate and inaccurate sim!
const Node& node = mIslandManager.getNode(nodeIndices[i]);
const Node& speculativeNode = mSpeculativeIslandManager.getNode(nodeIndices[i]);
//KS - we need to verify that the bodies in the "deactivating" list are still candidates for deactivation. There are cases where they may not no longer be candidates, e.g. if the application
//put bodies to sleep and activated them
if(node.isActive() && !speculativeNode.isActive())
return false;
}
return true;
}
void ThirdPassTask::runInternal()
{
PX_PROFILE_ZONE("Basic.thirdPassIslandGen", mIslandSim.getContextId());
mIslandSim.removeDestroyedEdges();
mIslandSim.processLostEdges(mIslandManager.mDestroyedNodes, true, true, mIslandManager.mMaxDirtyNodesPerFrame);
}
void PostThirdPassTask::runInternal()
{
for (PxU32 a = 0; a < mIslandManager.mDestroyedNodes.size(); ++a)
{
mIslandManager.mNodeHandles.freeHandle(mIslandManager.mDestroyedNodes[a].index());
}
mIslandManager.mDestroyedNodes.clear();
for (PxU32 a = 0; a < mIslandManager.mDestroyedEdges.size(); ++a)
{
mIslandManager.mEdgeHandles.freeHandle(mIslandManager.mDestroyedEdges[a]);
}
mIslandManager.mDestroyedEdges.clear();
PX_ASSERT(mIslandManager.validateDeactivations());
}
void SimpleIslandManager::thirdPassIslandGen(PxBaseTask* continuation)
{
mIslandManager.clearDeactivations();
mPostThirdPassTask.setContinuation(continuation);
mSpeculativeThirdPassTask.setContinuation(&mPostThirdPassTask);
mAccurateThirdPassTask.setContinuation(&mPostThirdPassTask);
mSpeculativeThirdPassTask.removeReference();
mAccurateThirdPassTask.removeReference();
mPostThirdPassTask.removeReference();
//PX_PROFILE_ZONE("Basic.thirdPassIslandGen", getContextId());
//mSpeculativeIslandManager.removeDestroyedEdges();
//mSpeculativeIslandManager.processLostEdges(mDestroyedNodes, true, true);
//mIslandManager.removeDestroyedEdges();
//mIslandManager.processLostEdges(mDestroyedNodes, true, true);
}
bool SimpleIslandManager::checkInternalConsistency()
{
return mIslandManager.checkInternalConsistency() && mSpeculativeIslandManager.checkInternalConsistency();
}
void SimpleIslandManager::clearDestroyedEdges()
{
mDestroyedPartitionEdges.forceSize_Unsafe(0);
}
void SimpleIslandManager::setEdgeConnected(EdgeIndex edgeIndex)
{
if(!mConnectedMap.test(edgeIndex))
{
mIslandManager.addContactManager(reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeIndex]), mEdgeNodeIndices[edgeIndex * 2], mEdgeNodeIndices[edgeIndex * 2 + 1], edgeIndex);
mConnectedMap.set(edgeIndex);
}
}
bool SimpleIslandManager::getIsEdgeConnected(EdgeIndex edgeIndex)
{
return !!mConnectedMap.test(edgeIndex);
}
void SimpleIslandManager::deactivateEdge(const EdgeIndex edgeIndex)
{
if (mFirstPartitionEdges[edgeIndex])
{
mDestroyedPartitionEdges.pushBack(mFirstPartitionEdges[edgeIndex]);
mFirstPartitionEdges[edgeIndex] = NULL;
}
}
void SimpleIslandManager::setEdgeDisconnected(EdgeIndex edgeIndex)
{
if(mConnectedMap.test(edgeIndex))
{
//PX_ASSERT(!mIslandManager.getEdge(edgeIndex).isInDirtyList());
mIslandManager.removeConnection(edgeIndex);
mConnectedMap.reset(edgeIndex);
}
}
void SimpleIslandManager::setEdgeRigidCM(const EdgeIndex edgeIndex, PxsContactManager* cm)
{
mConstraintOrCm[edgeIndex] = cm;
cm->getWorkUnit().mEdgeIndex = edgeIndex;
}
void SimpleIslandManager::clearEdgeRigidCM(const EdgeIndex edgeIndex)
{
mConstraintOrCm[edgeIndex] = NULL;
if (mFirstPartitionEdges[edgeIndex])
{
//this is the partition edges created/updated by the gpu solver
mDestroyedPartitionEdges.pushBack(mFirstPartitionEdges[edgeIndex]);
mFirstPartitionEdges[edgeIndex] = NULL;
}
}
void SimpleIslandManager::setKinematic(IG::NodeIndex nodeIndex)
{
mIslandManager.setKinematic(nodeIndex);
mSpeculativeIslandManager.setKinematic(nodeIndex);
}
void SimpleIslandManager::setDynamic(IG::NodeIndex nodeIndex)
{
mIslandManager.setDynamic(nodeIndex);
mSpeculativeIslandManager.setDynamic(nodeIndex);
}
}
}