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/SimulationController/src/ScShapeInteraction.h | |
| 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/SimulationController/src/ScShapeInteraction.h')
| -rw-r--r-- | PhysX_3.4/Source/SimulationController/src/ScShapeInteraction.h | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/SimulationController/src/ScShapeInteraction.h b/PhysX_3.4/Source/SimulationController/src/ScShapeInteraction.h new file mode 100644 index 00000000..fcfc8f44 --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/ScShapeInteraction.h @@ -0,0 +1,402 @@ +// 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 PX_COLLISION_SHAPE_INTERACTION +#define PX_COLLISION_SHAPE_INTERACTION + +#include "ScRbElementInteraction.h" +#include "ScActorPair.h" +#include "ScScene.h" +#include "ScBodySim.h" +#include "PxsContactManager.h" +#include "PxsContext.h" +#include "PxsSimpleIslandManager.h" + +#define INVALID_REPORT_PAIR_ID 0xffffffff + +namespace physx +{ +class PxsContactManagerOutputIterator; +namespace Sc +{ + /* + Description: A ShapeInteraction represents a pair of objects which _may_ have contacts. Created by the broadphase + and processed by the NPhaseCore. + */ + class ShapeInteraction : public RbElementInteraction + { + friend class NPhaseCore; + ShapeInteraction& operator=(const ShapeInteraction&); + public: + enum SiFlag + { + PAIR_FLAGS_MASK = (PxPairFlag::eNEXT_FREE - 1), // Bits where the PxPairFlags get stored + NEXT_FREE = ((PAIR_FLAGS_MASK << 1) & ~PAIR_FLAGS_MASK), + + HAS_TOUCH = (NEXT_FREE << 0), // Tracks the last know touch state + HAS_NO_TOUCH = (NEXT_FREE << 1), // Tracks the last know touch state + TOUCH_KNOWN = (HAS_TOUCH | HAS_NO_TOUCH), // If none of these flags is set, the touch state is not known (for example, this is true for pairs that never ran narrowphase + + CONTACTS_COLLECT_POINTS = (NEXT_FREE << 2), // The user wants to get the contact points (includes debug rendering) + CONTACTS_RESPONSE_DISABLED = (NEXT_FREE << 3), // Collision response disabled (either by the user through PxPairFlag::eSOLVE_CONTACT or because the pair has two kinematics) + + CONTACT_FORCE_THRESHOLD_PAIRS = PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST), + CONTACT_REPORT_EVENTS = PxU32(PxPairFlag::eNOTIFY_TOUCH_FOUND) | PxU32(PxPairFlag::eNOTIFY_TOUCH_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_TOUCH_LOST) | + PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST), + CONTACT_REPORT_EXTRA_DATA = PxU32(PxPairFlag::ePRE_SOLVER_VELOCITY) | PxU32(PxPairFlag::ePOST_SOLVER_VELOCITY) | PxU32(PxPairFlag::eCONTACT_EVENT_POSE), + + FORCE_THRESHOLD_EXCEEDED_NOW = (NEXT_FREE << 4), + FORCE_THRESHOLD_EXCEEDED_BEFORE = (NEXT_FREE << 5), + FORCE_THRESHOLD_EXCEEDED_FLAGS = FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE, + + IS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 6), // The pair is in the list of persistent contact events + WAS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 7), // The pair is inactive but used to be in the list of persistent contact events + IN_PERSISTENT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | WAS_IN_PERSISTENT_EVENT_LIST, + IS_IN_FORCE_THRESHOLD_EVENT_LIST= (NEXT_FREE << 8), // The pair is in the list of force threshold contact events + IS_IN_CONTACT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | IS_IN_FORCE_THRESHOLD_EVENT_LIST, + + LL_MANAGER_RECREATE_EVENT = CONTACT_REPORT_EVENTS | CONTACTS_COLLECT_POINTS | + CONTACTS_RESPONSE_DISABLED | PxU32(PxPairFlag::eMODIFY_CONTACTS) + }; + ShapeInteraction(ShapeSim& s1, ShapeSim& s2, ActorPair* aPair, PxPairFlags pairFlags, PxsContactManager* contactManager); + virtual ~ShapeInteraction(); + + // Submits to contact stream + void processUserNotification(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, const PxU32 ccdPass, const bool useCurrentTransform, + PxsContactManagerOutputIterator& outputs); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes + + void visualize(Cm::RenderOutput&, PxsContactManagerOutputIterator&); + + PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs); + + bool managerLostTouch(const PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs, bool useAdaptiveForce); + void managerNewTouch(const PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs, bool useAdaptiveForce); + + PX_FORCE_INLINE void adjustCountersOnLostTouch(BodySim*, BodySim*, bool useAdaptiveForce); + PX_FORCE_INLINE void adjustCountersOnNewTouch(bool useAdaptiveForce); + + PX_FORCE_INLINE void sendCCDRetouch(const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs); + void setContactReportPostSolverVelocity(ContactStreamManager& cs); + PX_FORCE_INLINE void sendLostTouchReport(bool shapeVolumeRemoved, const PxU32 ccdPass, PxsContactManagerOutputIterator& ouptuts); + void resetManagerCachedState() const; + + PX_FORCE_INLINE ActorPair* getActorPair() const { return mActorPair; } + PX_FORCE_INLINE void setActorPair(ActorPair& aPair) { mActorPair = &aPair; } + PX_FORCE_INLINE void clearActorPair() { mActorPair = NULL; } + PX_FORCE_INLINE ActorPairReport& getActorPairReport() const { return ActorPairReport::cast(*mActorPair); } + PX_INLINE Ps::IntBool isReportPair() const { /*PX_ASSERT(!(Ps::IntBool(getPairFlags() & CONTACT_REPORT_EVENTS)) || mActorPair->isReportPair());*/ return Ps::IntBool(getPairFlags() & CONTACT_REPORT_EVENTS); } + PX_INLINE Ps::IntBool hasTouch() const { return readFlag(HAS_TOUCH); } + PX_INLINE Ps::IntBool hasCCDTouch() const { PX_ASSERT(mManager); return mManager->getHadCCDContact(); } + PX_INLINE void swapAndClearForceThresholdExceeded(); + + PX_FORCE_INLINE void raiseFlag(SiFlag flag) { mFlags |= flag; } + PX_FORCE_INLINE Ps::IntBool readFlag(SiFlag flag) const { return Ps::IntBool(mFlags & flag); } + PX_FORCE_INLINE PxU32 getPairFlags() const; + + PX_FORCE_INLINE void removeFromReportPairList(); + + void onShapeChangeWhileSleeping(bool shapeOfDynamicChanged); + + PX_FORCE_INLINE Ps::IntBool hasKnownTouchState() const; + + virtual bool onActivate(void* data); + virtual bool onDeactivate(PxU32 infoFlag); + + void updateState(const PxU8 externalDirtyFlags); + + const PxsContactManager* getContactManager() const { return mManager; } + + void clearIslandGenData(); + + PX_FORCE_INLINE PxU32 getEdgeIndex() const { return mEdgeIndex; } + + private: + PxU32 mContactReportStamp; + PxU32 mFlags; + ActorPair* mActorPair; + PxU32 mReportPairIndex; // Owned by NPhaseCore for its report pair list + + PxsContactManager* mManager; + + PxU32 mEdgeIndex; + + PxU16 mReportStreamIndex; // position of this pair in the contact report stream + + // Internal functions: + + void createManager(void* contactManager); + PX_INLINE void resetManager(); + PX_INLINE bool updateManager(void* contactManager); + PX_INLINE void destroyManager(); + PX_FORCE_INLINE bool activeManagerAllowed() const; + PX_FORCE_INLINE PxU32 getManagerContactState() const { return mFlags & LL_MANAGER_RECREATE_EVENT; } + + PX_FORCE_INLINE void clearFlag(SiFlag flag) { mFlags &= ~flag; } + PX_INLINE void setFlag(SiFlag flag, bool value) + { + if (value) + raiseFlag(flag); + else + clearFlag(flag); + } + PX_FORCE_INLINE void setHasTouch() { clearFlag(HAS_NO_TOUCH); raiseFlag(HAS_TOUCH); } + PX_FORCE_INLINE void setHasNoTouch() { clearFlag(HAS_TOUCH); raiseFlag(HAS_NO_TOUCH); } + + PX_FORCE_INLINE void setPairFlags(PxPairFlags flags); + + PX_FORCE_INLINE void processReportPairOnActivate(); + PX_FORCE_INLINE void processReportPairOnDeactivate(); + + // Certain SiFlag cache properties of the pair. If these properties change then the flags have to be updated. + // For example: is collision enabled for this pair? are contact points requested for this pair? + PX_FORCE_INLINE void updateFlags(const Sc::Scene&, const Sc::BodySim*, const Sc::BodySim*, const PxU32 pairFlags); + + friend class Sc::Scene; + }; + +} // namespace Sc + + +PX_FORCE_INLINE void Sc::ShapeInteraction::sendLostTouchReport(bool shapeVolumeRemoved, const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs) +{ + PX_ASSERT(hasTouch()); + PX_ASSERT(isReportPair()); + + PxU32 thresholdForceLost = readFlag(ShapeInteraction::FORCE_THRESHOLD_EXCEEDED_NOW) ? PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST) : 0; // make sure to only send report if force is still above threshold + PxU32 triggeredFlags = getPairFlags() & (PxU32(PxPairFlag::eNOTIFY_TOUCH_LOST) | thresholdForceLost); + if (triggeredFlags) + { + PxU16 infoFlag = 0; + if (mActorPair->getTouchCount() == 1) // this code assumes that the actor pair touch count does get decremented afterwards + { + infoFlag |= PxContactPairFlag::eACTOR_PAIR_LOST_TOUCH; + } + + //Lost touch is processed after solver, so we should use the previous transform to update the pose for objects if user request eCONTACT_EVENT_POSE + processUserNotification(triggeredFlags, infoFlag, true, ccdPass, false, outputs); + } + + ActorPairReport& apr = getActorPairReport(); + if (apr.hasReportData() && !apr.streamResetNeeded(getScene().getTimeStamp())) + { + // If there has been no event recorded yet, there is no need to worry about events with shape pointers which might later reference + // removed shapes due to buffered removal, i.e., removal while the simulation was running. + // This is also correct for CCD scenarios where a touch could get lost and then found again etc. If in such a case there ever is a contact event + // recorded, there will always be another sendLostTouchReport() call at some later point (caused by the simulation or when the shape gets + // removed at fetchResults). + PxU16 flagsToRaise = ContactStreamManagerFlag::eHAS_PAIRS_THAT_LOST_TOUCH; + + ContactStreamManager& cs = apr.getContactStreamManager(); + + if (shapeVolumeRemoved) + { + flagsToRaise |= ContactStreamManagerFlag::eTEST_FOR_REMOVED_SHAPES; + + // if an actor gets deleted while the simulation is running and the actor has a pending contact report with post solver + // velocity extra data, then the post solver velocity needs to get written now because it is too late when the reports + // get fired (the object will have been deleted already) + + if (cs.getFlags() & ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY) + setContactReportPostSolverVelocity(cs); + } + + cs.raiseFlags(flagsToRaise); + } +} + + +PX_FORCE_INLINE void Sc::ShapeInteraction::setPairFlags(PxPairFlags flags) +{ + PX_ASSERT(PxU32(flags) < PxPairFlag::eNEXT_FREE); // to find out if a new PxPairFlag has been added after eLAST instead of in front + + PxU32 newFlags = mFlags; + PxU32 fl = PxU32(flags) & PAIR_FLAGS_MASK; + newFlags &= (~PAIR_FLAGS_MASK); // clear old flags + newFlags |= fl; + + mFlags = newFlags; +} + + +// PT: returning PxU32 instead of PxPairFlags to remove LHS. Please do not undo this. +PX_FORCE_INLINE PxU32 Sc::ShapeInteraction::getPairFlags() const +{ + return (mFlags & PAIR_FLAGS_MASK); +} + + +PX_INLINE void Sc::ShapeInteraction::swapAndClearForceThresholdExceeded() +{ + PxU32 flags = mFlags; + + PX_COMPILE_TIME_ASSERT(FORCE_THRESHOLD_EXCEEDED_NOW == (FORCE_THRESHOLD_EXCEEDED_BEFORE >> 1)); + + PxU32 nowToBefore = (flags & FORCE_THRESHOLD_EXCEEDED_NOW) << 1; + flags &= ~(FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE); + flags |= nowToBefore; + + mFlags = flags; +} + +PX_FORCE_INLINE void Sc::ShapeInteraction::removeFromReportPairList() +{ + // this method should only get called if the pair is in the list for + // persistent or force based contact reports + PX_ASSERT(mReportPairIndex != INVALID_REPORT_PAIR_ID); + PX_ASSERT(readFlag(IS_IN_CONTACT_EVENT_LIST)); + + Scene& scene = getScene(); + + if (readFlag(IS_IN_FORCE_THRESHOLD_EVENT_LIST)) + scene.getNPhaseCore()->removeFromForceThresholdContactEventPairs(this); + else + { + PX_ASSERT(readFlag(IS_IN_PERSISTENT_EVENT_LIST)); + scene.getNPhaseCore()->removeFromPersistentContactEventPairs(this); + } +} + +PX_INLINE bool Sc::ShapeInteraction::updateManager(void* contactManager) +{ + if (activeManagerAllowed()) + { + if (mManager == 0) + createManager(contactManager); + + return (mManager != NULL); // creation might fail (pool reached limit, mem allocation failed etc.) + } + else + return false; +} + +PX_INLINE void Sc::ShapeInteraction::destroyManager() +{ + PX_ASSERT(mManager); + + Scene& scene = getScene(); + + PxvNphaseImplementationContext* nphaseImplementationContext = scene.getLowLevelContext()->getNphaseImplementationContext(); + PX_ASSERT(nphaseImplementationContext); + nphaseImplementationContext->unregisterContactManager(mManager); + + /*if (mEdgeIndex != IG_INVALID_EDGE) + scene.getSimpleIslandManager()->clearEdgeRigidCM(mEdgeIndex);*/ + scene.getLowLevelContext()->destroyContactManager(mManager); + mManager = 0; +} + + +PX_FORCE_INLINE bool Sc::ShapeInteraction::activeManagerAllowed() const +{ + PX_ASSERT(getShape0().getActor().isDynamicRigid() || getShape1().getActor().isDynamicRigid()); + + const BodySim* bodySim0 = getShape0().getBodySim(); + const BodySim* bodySim1 = getShape1().getBodySim(); + PX_ASSERT(bodySim0); // the first shape always belongs to a dynamic body + + const IG::IslandSim& islandSim = getScene().getSimpleIslandManager()->getSpeculativeIslandSim(); + + //if((bodySim0->isActive()) || (bodySim1 && bodySim1->isActive())) + //check whether active in the speculative sim! + if (islandSim.getNode(bodySim0->getNodeIndex()).isActive() || + (bodySim1 && islandSim.getNode(bodySim1->getNodeIndex()).isActive())) + { + return true; + } + else + { + //Sleeping kinematic 0 vs sleeping kinematic 1 + return false; + } +} + + +PX_FORCE_INLINE void Sc::ShapeInteraction::sendCCDRetouch(const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs) +{ + PxU32 pairFlags = getPairFlags(); + if (pairFlags & PxPairFlag::eNOTIFY_TOUCH_CCD) + { + processUserNotification(PxPairFlag::eNOTIFY_TOUCH_CCD, 0, false, ccdPass, false, outputs); + } +} + + +PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnLostTouch(BodySim* body0, BodySim* body1, bool useAdaptiveForce) +{ + PX_ASSERT(body0); // the first shape always belongs to a dynamic body + + PX_ASSERT(mActorPair->getTouchCount()); + + mActorPair->decTouchCount(); + + if (useAdaptiveForce || mActorPair->getTouchCount() == 0) + { + body0->decrementBodyConstraintCounter(); + if (body1) + body1->decrementBodyConstraintCounter(); + } +} + + +PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnNewTouch(bool useAdaptiveForce) +{ + BodySim* body0 = getShape0().getBodySim(); + BodySim* body1 = getShape1().getBodySim(); + PX_ASSERT(body0); // the first shape always belongs to a dynamic body + + mActorPair->incTouchCount(); + //If using adaptive force, always record a body constraint, otherwise only record if this is the first constraint + //with this pair of bodies (doubling up usage of this counter for both adaptive force and stabilization) + if (useAdaptiveForce || mActorPair->getTouchCount() == 1) + { + body0->incrementBodyConstraintCounter(); + if (body1) + body1->incrementBodyConstraintCounter(); + } +} + + +PX_FORCE_INLINE Ps::IntBool Sc::ShapeInteraction::hasKnownTouchState() const +{ + // For a pair where the bodies were added asleep, the touch state is not known until narrowphase runs on the pair for the first time. + // If such a pair looses AABB overlap before, the conservative approach is to wake the bodies up. This method provides an indicator that + // this is such a pair. Note: this might also wake up objects that do not touch but that's the price to pay (unless we want to run + // overlap tests on such pairs). + + if (mManager) + return mManager->touchStatusKnown(); + else + return readFlag(TOUCH_KNOWN); +} + + +} + +#endif |