diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/LowLevel/software/include | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/LowLevel/software/include')
20 files changed, 4177 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsBodySim.h b/PhysX_3.4/Source/LowLevel/software/include/PxsBodySim.h new file mode 100644 index 00000000..93aafc41 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsBodySim.h @@ -0,0 +1,52 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 mBodySimIndex; //8 or 12 + PxU32 mUpdated; //12 or 16 +}; + +}//physx + +#endif diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsCCD.h b/PhysX_3.4/Source/LowLevel/software/include/PxsCCD.h new file mode 100644 index 00000000..32ec53d3 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsCCD.h @@ -0,0 +1,617 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "Ps.h" +#include "PxGeometry.h" +#include "GuCCDSweepConvexMesh.h" +#include "PsHashMap.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 : Gu::CCDShape +{ +public: + const PxsShapeCore* mShapeCore; //Shape core (can be shared) + const PxsRigidCore* mRigidCore; //Rigid body core + + /** + \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. + + + + /** + \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. + + 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); + /** + \brief Performs a sweep estimation for this pair + \return The normalized TOI. <= 1.0 indicates a potential hit, otherwise PX_MAX_REAL. + */ + PxReal sweepEstimateToi(); + /** + \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); + + /** + \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); } + + /** + \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] disableResweep If this is true, we perform a reduced-fidelity CCD approach + */ + void updateCCD(PxReal dt, PxBaseTask* continuation, 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); + /** + \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; + +private: + + PX_NOCOPY(PxsCCDContext) +}; + + +} + + + +#endif + diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsContactManager.h b/PhysX_3.4/Source/LowLevel/software/include/PxsContactManager.h new file mode 100644 index 00000000..197b4afa --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsContactManager.h @@ -0,0 +1,178 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsContactManagerState.h b/PhysX_3.4/Source/LowLevel/software/include/PxsContactManagerState.h new file mode 100644 index 00000000..a06a2063 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsContactManagerState.h @@ -0,0 +1,95 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsContext.h b/PhysX_3.4/Source/LowLevel/software/include/PxsContext.h new file mode 100644 index 00000000..d50cff15 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsContext.h @@ -0,0 +1,369 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxvContext.h" +#include "PxvNphaseImplementationContext.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; + +namespace Cm +{ + class FlushPool; +} + +namespace Bp +{ + class AABBManagerImpl; +} + +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 PxsCMUpdateTask : public Cm::Task +{ +public: + + static const PxU32 BATCH_SIZE = 128; + + PxsCMUpdateTask(PxsContext* context, PxReal dt, PxsContactManager** cmArray, PxsContactManagerOutput* cmOutputs, Gu::Cache* caches, PxU32 cmCount, + PxContactModifyCallback* callback): + mCmArray(cmArray), mCmOutputs(cmOutputs), mCaches(caches), mCmCount(cmCount), mDt(dt), mContext(context), mCallback(callback) + { + } + + virtual void release(); + + /*PX_FORCE_INLINE void insert(PxsContactManager* cm) + { + PX_ASSERT(mCmCount < BATCH_SIZE); + mCmArray[mCmCount++]=cm; + }*/ + +protected: + //PxsContactManager* mCmArray[BATCH_SIZE]; + PxsContactManager** mCmArray; + PxsContactManagerOutput* mCmOutputs; + Gu::Cache* mCaches; + PxU32 mCmCount; + PxReal mDt; //we could probably retrieve from context to save space? + PxsContext* mContext; + PxContactModifyCallback* mCallback; +}; + +class PxsContext : public Ps::UserAllocated, public PxcNpContext +{ + PX_NOCOPY(PxsContext) +public: + PxsContext( const PxSceneDesc& desc, PxTaskManager*, Cm::FlushPool&, 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 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; + + + // 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsDefaultMemoryManager.h b/PhysX_3.4/Source/LowLevel/software/include/PxsDefaultMemoryManager.h new file mode 100644 index 00000000..baabbd86 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsDefaultMemoryManager.h @@ -0,0 +1,98 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsHeapMemoryAllocator.h b/PhysX_3.4/Source/LowLevel/software/include/PxsHeapMemoryAllocator.h new file mode 100644 index 00000000..61d600dc --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsHeapMemoryAllocator.h @@ -0,0 +1,68 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "DyGpuAPI.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
\ No newline at end of file diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsIncrementalConstraintPartitioning.h b/PhysX_3.4/Source/LowLevel/software/include/PxsIncrementalConstraintPartitioning.h new file mode 100644 index 00000000..279e3666 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsIncrementalConstraintPartitioning.h @@ -0,0 +1,40 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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
\ No newline at end of file diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsIslandManagerTypes.h b/PhysX_3.4/Source/LowLevel/software/include/PxsIslandManagerTypes.h new file mode 100644 index 00000000..01f7b4ee --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsIslandManagerTypes.h @@ -0,0 +1,372 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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; +} + +#if PX_USE_16_BIT_HANDLES +typedef PxU16 NodeType; +typedef PxU16 EdgeType; +typedef PxU16 IslandType; +#define INVALID_NODE 0xffff +#define INVALID_EDGE 0xffff +#define INVALID_ISLAND 0xffff +#else +typedef PxU32 NodeType; +typedef PxU32 EdgeType; +typedef PxU32 IslandType; +#define INVALID_NODE 0xffffffff +#define INVALID_EDGE 0xffffffff +#define INVALID_ISLAND 0xffffffff +#endif + +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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsIslandSim.h b/PhysX_3.4/Source/LowLevel/software/include/PxsIslandSim.h new file mode 100644 index 00000000..48cfc7d2 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsIslandSim.h @@ -0,0 +1,965 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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" + +namespace physx +{ + +namespace Dy +{ + struct Constraint; + class Articulation; +} + +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_NODE 0x3FFFFFFu +#define IG_INVALID_LINK 0xFFu + +typedef PxU32 IslandId; +typedef PxU32 EdgeIndex; +typedef PxU32 EdgeInstanceIndex; + +class IslandSim; + + + +class NodeIndex +{ +private: + PxU32 ind; + +public: + + explicit PX_FORCE_INLINE NodeIndex(PxU32 id = IG_INVALID_NODE, PxU32 articId = 0) : ind((id<<6) | articId) + { + } + + PxU32 index() const { return ind>>6; } + PxU32 articulationLinkId() const { return (ind & 63); } + + bool isStaticBody() const { return (ind>>6) == IG_INVALID_NODE; } + + bool isValid() const { return (ind>>6) != IG_INVALID_NODE; } + + void setIndices(PxU32 index, PxU32 articId) { ind = ((index<<6) | articId); } +}; + +union ConstraintOrContactManager +{ + PxsContactManager* mCm; + Dy::Constraint* mConstraint; +}; + + +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. + union + { + PxsRigidBody* mRigidBody; + Dy::Articulation* 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::Articulation* 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 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 + Ps::Array<Edge> mEdges; //! Edges used to represent contacts or constraints + //Ps::Array<ConstraintOrContactManager> mConstraintOrCm; //! Pointers to either the constraint or Cm for this pair + Ps::Array<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> mActiveEdges[Edge::eEDGE_TYPE_COUNT]; //! An array of active edges + 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 mInitialActiveEdgeCount[Edge::eEDGE_TYPE_COUNT]; + 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; + Ps::Array<NodeIndex>& mEdgeNodeIndices; + Ps::Array<physx::PartitionEdge*>* mDestroyedPartitionEdges; + + PxU32* mNpIndexPtr; + + PxU64 mContextId; + +public: + + IslandSim(Ps::Array<PartitionEdge*>* firstPartitionEdges, Ps::Array<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::Articulation* 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::Articulation* 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 mType; //! The type of constraint this is + PxU32 mPartitionEntryIndex; //! index of partition edges for this partition +}; + +struct PartitionNodeData +{ + PxU32 mNodeIndex0; + PxU32 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 mInfiniteMass1; //! Whether body 1 is kinematic + + 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 + + PartitionEdge() : mEdgeIndex(IG_INVALID_EDGE), mInfiniteMass0(false), + mInfiniteMass1(false), mNextPatch(NULL) + { + } +}; + +} + +#endif diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsKernelWrangler.h b/PhysX_3.4/Source/LowLevel/software/include/PxsKernelWrangler.h new file mode 100644 index 00000000..494ab4f7 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsKernelWrangler.h @@ -0,0 +1,50 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "DyGpuAPI.h" +#include "foundation/PxSimpleTypes.h" + +namespace physx +{ + class KernelWrangler; + class PxGpuDispatcher; + class PxErrorCallback; + + class PxsKernelWranglerManager + { + public: + virtual ~PxsKernelWranglerManager(){} + virtual KernelWrangler* getKernelWrangler() = 0; + }; +} +#endif
\ No newline at end of file diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsMaterialCombiner.h b/PhysX_3.4/Source/LowLevel/software/include/PxsMaterialCombiner.h new file mode 100644 index 00000000..4f6a3dfc --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsMaterialCombiner.h @@ -0,0 +1,143 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsMemoryManager.h b/PhysX_3.4/Source/LowLevel/software/include/PxsMemoryManager.h new file mode 100644 index 00000000..1f5193dd --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsMemoryManager.h @@ -0,0 +1,62 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "DyGpuAPI.h" +#include "CmPhysXCommon.h" + +namespace physx +{ + namespace shdfnd + { + class VirtualAllocatorCallback; + } + + class PxGpuDispatcher; + + 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsNphaseImplementationContext.h b/PhysX_3.4/Source/LowLevel/software/include/PxsNphaseImplementationContext.h new file mode 100644 index 00000000..e6d9b8e9 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsNphaseImplementationContext.h @@ -0,0 +1,142 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 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() {} + + + + Ps::Array<PxU32> mRemovedContactManagers; + PxsContactManagers mNarrowPhasePairs; + PxsContactManagers mNewNarrowPhasePairs; + + PxContactModifyCallback* mModifyCallback; + + IG::IslandSim* mIslandSim; + +private: + + void unregisterContactManagerInternal(PxU32 npIndex, PxsContactManagers& managers, PxsContactManagerOutput* cmOutputs); + + PX_NOCOPY(PxsNphaseImplementationContext) +}; + +} + +#endif diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsRigidBody.h b/PhysX_3.4/Source/LowLevel/software/include/PxsRigidBody.h new file mode 100644 index 00000000..0bbfc8ec --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsRigidBody.h @@ -0,0 +1,168 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_BODYATOM_H +#define PXS_BODYATOM_H + +#include "PxcRigidBody.h" +#include "PxvDynamics.h" + +namespace physx +{ + +class PxsRigidBody : public PxcRigidBody +{ + public: + PX_FORCE_INLINE PxsRigidBody(PxsBodyCore* core) : PxcRigidBody(core) { } + PX_FORCE_INLINE ~PxsRigidBody() {} + + PX_FORCE_INLINE const PxTransform& getPose() const { PX_ASSERT(mCore->body2World.isSane()); return mCore->body2World; } + + //PX_FORCE_INLINE const Cm::SpatialVector& getAccelerationV() const { return mAcceleration; } + //PX_FORCE_INLINE void setAccelerationV(const Cm::SpatialVector& v) { mAcceleration = v; } + + 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; } + + // AP newccd todo: merge into get both velocities, compute inverse transform once, precompute mLastTransform.getInverse() + PX_FORCE_INLINE PxVec3 getLinearMotionVelocity(PxReal invDt) const { + // delta(t0(x))=t1(x) + // delta(t0(t0`(x)))=t1(t0`(x)) + // delta(x)=t1(t0`(x)) + PxVec3 deltaP = mCore->body2World.p - getLastCCDTransform().p; + return deltaP * invDt; + } + PX_FORCE_INLINE PxVec3 getAngularMotionVelocity(PxReal invDt) const { + PxQuat deltaQ = mCore->body2World.q * getLastCCDTransform().q.getConjugate(); + PxVec3 axis; + PxReal angle; + deltaQ.toRadiansAndUnitAxis(angle, axis); + return axis * angle * invDt; + } + PX_FORCE_INLINE PxVec3 getLinearMotionVelocity(PxReal dt, const PxsBodyCore* PX_RESTRICT bodyCore) const { + // delta(t0(x))=t1(x) + // delta(t0(t0`(x)))=t1(t0`(x)) + // delta(x)=t1(t0`(x)) + PxVec3 deltaP = bodyCore->body2World.p - getLastCCDTransform().p; + return deltaP * 1.0f / dt; + } + PX_FORCE_INLINE PxVec3 getAngularMotionVelocity(PxReal dt, const PxsBodyCore* PX_RESTRICT bodyCore) const { + PxQuat deltaQ = bodyCore->body2World.q * getLastCCDTransform().q.getConjugate(); + PxVec3 axis; + PxReal angle; + deltaQ.toRadiansAndUnitAxis(angle, axis); + return axis * angle * 1.0f/dt; + } + + PX_FORCE_INLINE 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 | eDISABLE_GRAVITY); } + + void advanceToToi(PxReal toi, PxReal dt, bool clip); + void advancePrevPoseToToi(PxReal toi); + PxTransform getAdvancedTransform(PxReal toi) const; + Cm::SpatialVector getPreSolverVelocities() const; + + +}; + +void PxsRigidBody::constrainLinearVelocity() +{ + const PxU32 lockFlags = mCore->lockFlags; + + if (lockFlags) + { + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_X) + mCore->linearVelocity.x = 0.f; + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Y) + mCore->linearVelocity.y = 0.f; + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Z) + mCore->linearVelocity.z = 0.f; + } +} + +void PxsRigidBody::constrainAngularVelocity() +{ + const PxU32 lockFlags = mCore->lockFlags; + + if (lockFlags) + { + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_X) + mCore->angularVelocity.x = 0.f; + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y) + mCore->angularVelocity.y = 0.f; + if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z) + mCore->angularVelocity.z = 0.f; + } +} + +} + +#endif diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsShapeSim.h b/PhysX_3.4/Source/LowLevel/software/include/PxsShapeSim.h new file mode 100644 index 00000000..0bf63f2e --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsShapeSim.h @@ -0,0 +1,52 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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" + +namespace physx +{ + +//PxsBodySim is 12 or 16 bytes +struct PxsShapeSim// : public PxsBodySim +{ + PxsShapeCore* mShapeCore; // 4 or 8 + PxU32 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsSimpleIslandManager.h b/PhysX_3.4/Source/LowLevel/software/include/PxsSimpleIslandManager.h new file mode 100644 index 00000000..50291b8f --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsSimpleIslandManager.h @@ -0,0 +1,207 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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(SimpleIslandManager& islandManager, IslandSim& islandSim) : mIslandManager(islandManager), mIslandSim(islandSim) + { + } + + virtual void runInternal(); + + virtual const char* getName() const + { + return "ThirdPassIslandGenTask"; + } + +private: + PX_NOCOPY(ThirdPassTask) +}; + +class PostThirdPassTask : public Cm::Task +{ + SimpleIslandManager& mIslandManager; + +public: + + PostThirdPassTask(SimpleIslandManager& islandManager) : mIslandManager(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; + Ps::Array<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! + Ps::Array<NodeIndex> mEdgeNodeIndices; + + Ps::Array<ConstraintOrContactManager> 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::Articulation* 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 mConstraintOrCm[edgeId].mCm; } + PX_FORCE_INLINE PxsContactManager* getContactManagerUnsafe(IG::EdgeIndex edgeId) const { return mConstraintOrCm[edgeId].mCm; } + PX_FORCE_INLINE Dy::Constraint* getConstraint(IG::EdgeIndex edgeId) const { return mConstraintOrCm[edgeId].mConstraint; } + PX_FORCE_INLINE Dy::Constraint* getConstraintUnsafe(IG::EdgeIndex edgeId) const { return mConstraintOrCm[edgeId].mConstraint; } + + 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsSimulationController.h b/PhysX_3.4/Source/LowLevel/software/include/PxsSimulationController.h new file mode 100644 index 00000000..8d6c2612 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsSimulationController.h @@ -0,0 +1,135 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "DyGpuAPI.h" +#include "CmBitMap.h" +#include "PsArray.h" + + +namespace physx +{ + namespace Dy + { + class Context; + struct Constraint; + } + + namespace Cm + { + class EventProfiler; + } + + namespace Bp + { + class BoundsArray; + class BroadPhase; + } + + namespace IG + { + class SimpleIslandManager; + class IslandSim; + } + + class PxGpuDispatcher; + 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, Ps::VirtualAllocator>& jointIndices, + Ps::Array<PxgSolverConstraintManagerConstants, Ps::VirtualAllocator>& managerIter, PxU32 uniqueId) = 0; + virtual void removeJoint(const PxU32 edgeIndex, Dy::Constraint* constraint, Ps::Array<PxU32, Ps::VirtualAllocator>& 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 PxU32 nodeIndex) = 0; + virtual void addDynamics(PxsRigidBody** rigidBody, const PxU32* nodeIndex, PxU32 nbToProcess) = 0; + virtual void updateJoint(const PxU32 edgeIndex, Dy::Constraint* constraint) = 0; + virtual void updateBodies(PxsRigidBody** rigidBodies, PxU32* nodeIndices, const PxU32 nbBodies) = 0; + virtual void updateBody(PxsRigidBody* rigidBodies, const PxU32 nodeIndex) = 0; + virtual void updateBodiesAndShapes(PxBaseTask* continuation, bool extrudeHeightfields) = 0; + virtual void update(const PxU32 bitMapWordCounts) = 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 PxsBodySim* getBodySims() = 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; + + protected: + PxsSimulationControllerCallback* mCallback; + + }; + + PxsSimulationController* createSimulationController(PxsSimulationControllerCallback* callback); +} + +#endif diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxsTransformCache.h b/PhysX_3.4/Source/LowLevel/software/include/PxsTransformCache.h new file mode 100644 index 00000000..b9d69022 --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxsTransformCache.h @@ -0,0 +1,144 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PhysX_3.4/Source/LowLevel/software/include/PxvNphaseImplementationContext.h b/PhysX_3.4/Source/LowLevel/software/include/PxvNphaseImplementationContext.h new file mode 100644 index 00000000..84eddbca --- /dev/null +++ b/PhysX_3.4/Source/LowLevel/software/include/PxvNphaseImplementationContext.h @@ -0,0 +1,220 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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" + +#if PX_SUPPORT_GPU_PHYSX +#include "Pxg.h" +#endif + +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 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; + + + + +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; + +}; + +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 |