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/ScContactStream.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/ScContactStream.h')
| -rw-r--r-- | PhysX_3.4/Source/SimulationController/src/ScContactStream.h | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/SimulationController/src/ScContactStream.h b/PhysX_3.4/Source/SimulationController/src/ScContactStream.h new file mode 100644 index 00000000..163f119c --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/ScContactStream.h @@ -0,0 +1,422 @@ +// 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_PHYSICS_SCP_CONTACTSTREAM +#define PX_PHYSICS_SCP_CONTACTSTREAM + +#include "foundation/Px.h" +#include "PxSimulationEventCallback.h" +#include "ScObjectIDTracker.h" +#include "ScRigidSim.h" +#include "ScStaticSim.h" +#include "ScBodySim.h" + +namespace physx +{ + class PxShape; + +namespace Sc +{ + class ActorPair; + + + // Internal counterpart of PxContactPair + struct ContactShapePair + { + public: + PxShape* shapes[2]; + const PxU8* contactPatches; + const PxU8* contactPoints; + const PxReal* contactForces; + PxU32 requiredBufferSize; + PxU8 contactCount; + PxU8 patchCount; + PxU16 constraintStreamSize; + PxU16 flags; + PxU16 events; + PxU32 shapeID[2]; + //26 (or 38 on 64bit) + }; + PX_COMPILE_TIME_ASSERT(sizeof(ContactShapePair) == sizeof(PxContactPair)); + + struct ContactStreamManagerFlag + { + enum Enum + { + /** + \brief Need to test stream for shapes that were removed from the actor/scene + + Usually this is the case when a shape gets removed from the scene, however, other operations that remove the + broadphase volume of a pair object have to be considered as well since the shape might get removed later after such an + operation. The scenarios to consider are: + + \li shape gets removed (this includes raising PxActorFlag::eDISABLE_SIMULATION) + \li shape switches to eSCENE_QUERY_SHAPE only + \li shape switches to eTRIGGER_SHAPE + \li resetFiltering() + \li actor gets removed from an aggregate + + */ + eTEST_FOR_REMOVED_SHAPES = (1<<0), + + /** + \brief Invalid stream memory not allocated + */ + eINVALID_STREAM = (1<<1), + + /** + \brief Incomplete stream will be reported + */ + eINCOMPLETE_STREAM = (1<<2), + + /** + \brief The stream contains extra data with PxContactPairVelocity items where the post solver velocity needs to get written to. + Only valid for discrete collision (in CCD the post response velocity is available immediately). + */ + eNEEDS_POST_SOLVER_VELOCITY = (1<<3), + + /** + \brief Contains pairs that lost touch + + This info is used as an optimization to only parse the stream and check for removed shapes if there is a potential for + having removed shapes in the stream that won't get detected in any other way. For example, there is the scenario where + during the simulation a pair loses AABB touch and gets deleted. At that point a lost touch event might get written to the + stream. If at fetchResults a buffered shape removal takes place, and that shape was part of the mentioned pair, there is + no way any longer to make the connection to the corresponding event stream (since the pair has been deleted during the sim). + */ + eHAS_PAIRS_THAT_LOST_TOUCH = (1<<4), + + /** + \brief Marker for the next available free flag + */ + eNEXT_FREE_FLAG = (1<<5) + }; + }; + + struct ContactStreamHeader + { + PxU16 contactPass; // marker for extra data to know when a new collison pass started (discrete collision -> CCD pass 1 -> CCD pass 2 -> ...) + PxU16 pad; // to keep the stream 4byte aligned + }; + + /** + \brief Contact report logic and data management. + + The internal contact report stream has the following format: + + ContactStreamHeader | PxContactPairIndex0 | (PxContactPairPose0, PxContactPairVelocity0) | ... | PxContactPairIndexN | (PxContactPairPoseN, PxContactPairVelocityN) | (unused memory up to maxExtraDataSize ) | + PxContactPair0 | ... | PxContactPairM | (unsued pairs up to maxPairCount) + */ + class ContactStreamManager + { + public: + PX_FORCE_INLINE ContactStreamManager() : maxPairCount(0), flags_and_maxExtraDataBlocks(0) {} + PX_FORCE_INLINE ~ContactStreamManager() {} + + PX_FORCE_INLINE void reset(); + + PX_FORCE_INLINE PxU16 getFlags() const; + PX_FORCE_INLINE void raiseFlags(PxU16 flags); + PX_FORCE_INLINE void clearFlags(PxU16 flags); + + PX_FORCE_INLINE PxU32 getMaxExtraDataSize() const; + PX_FORCE_INLINE void setMaxExtraDataSize(PxU32 size); // size in bytes (will translate into blocks internally) + + PX_FORCE_INLINE Sc::ContactShapePair* getShapePairs(PxU8* contactReportPairData) const; + + PX_FORCE_INLINE static void convertDeletedShapesInContactStream(ContactShapePair*, PxU32 pairCount, const ObjectIDTracker&); + + PX_FORCE_INLINE static PxU32 computeExtraDataBlockCount(PxU32 extraDataSize); + PX_FORCE_INLINE static PxU32 computeExtraDataBlockSize(PxU32 extraDataSize); + PX_FORCE_INLINE static PxU16 computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader); + PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairVelocity*, PxU32 index, const RigidSim&, bool isCCDPass); + PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairPose*, PxU32 index, const RigidSim&, bool isCCDPass, const bool useCurrentTransform); + PX_FORCE_INLINE void fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const RigidSim&, const RigidSim&, PxU32 ccdPass, const bool useCurrentTransform, PxU32 pairIndex, PxU32 sizeOffset); + PX_FORCE_INLINE void setContactReportPostSolverVelocity(PxU8* stream, const RigidSim&, const RigidSim&); + + PxU32 bufferIndex; // marks the start of the shape pair stream of the actor pair (byte offset with respect to global contact buffer stream) + PxU16 maxPairCount; // used to reserve the same amount of memory as in the last frame (as an initial guess) + PxU16 currentPairCount; // number of shape pairs stored in the buffer + PxU16 extraDataSize; // size of the extra data section in the stream + private: + PxU16 flags_and_maxExtraDataBlocks; // used to reserve the same amount of memory as in the last frame (as an initial guess) + + public: + static const PxU32 sExtraDataBlockSizePow2 = 4; // extra data gets allocated as a multiple of 2^sExtraDataBlockSizePow2 to keep memory low of this struct. + static const PxU32 sFlagMask = (ContactStreamManagerFlag::eNEXT_FREE_FLAG - 1); + static const PxU32 sMaxExtraDataShift = 5; // shift necessary to extract the maximum number of blocks allocated for extra data + + PX_COMPILE_TIME_ASSERT(ContactStreamManagerFlag::eNEXT_FREE_FLAG == (1 << sMaxExtraDataShift)); + }; + +} // namespace Sc + + +PX_FORCE_INLINE void Sc::ContactStreamManager::reset() +{ + currentPairCount = 0; + extraDataSize = 0; + flags_and_maxExtraDataBlocks &= ~sFlagMask; +} + + +PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::getFlags() const +{ + return (flags_and_maxExtraDataBlocks & sFlagMask); +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::raiseFlags(PxU16 flags) +{ + PX_ASSERT(flags < ContactStreamManagerFlag::eNEXT_FREE_FLAG); + + flags_and_maxExtraDataBlocks |= flags; +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::clearFlags(PxU16 flags) +{ + PX_ASSERT(flags < ContactStreamManagerFlag::eNEXT_FREE_FLAG); + + PxU16 tmpFlags = getFlags(); + tmpFlags &= ~flags; + flags_and_maxExtraDataBlocks &= ~sFlagMask; + raiseFlags(tmpFlags); +} + + +PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::getMaxExtraDataSize() const +{ + return PxU32((flags_and_maxExtraDataBlocks >> sMaxExtraDataShift) << sExtraDataBlockSizePow2); +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::setMaxExtraDataSize(PxU32 size) +{ + PxU32 nbBlocks = computeExtraDataBlockCount(size); + flags_and_maxExtraDataBlocks = Ps::to16((flags_and_maxExtraDataBlocks & sFlagMask) | (nbBlocks << sMaxExtraDataShift)); +} + + +PX_FORCE_INLINE Sc::ContactShapePair* Sc::ContactStreamManager::getShapePairs(PxU8* contactReportPairData) const +{ + return reinterpret_cast<Sc::ContactShapePair*>(contactReportPairData + getMaxExtraDataSize()); +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::convertDeletedShapesInContactStream(ContactShapePair* shapePairs, PxU32 pairCount, const ObjectIDTracker& tracker) +{ + for(PxU32 i=0; i < pairCount; i++) + { + ContactShapePair& csp = shapePairs[i]; + + PxU32 shape0ID = csp.shapeID[0]; + PxU32 shape1ID = csp.shapeID[1]; + + PxU16 flags = csp.flags; + PX_COMPILE_TIME_ASSERT(sizeof(flags) == sizeof((reinterpret_cast<ContactShapePair*>(0))->flags)); + + if (tracker.isDeletedID(shape0ID)) + flags |= PxContactPairFlag::eREMOVED_SHAPE_0; + if (tracker.isDeletedID(shape1ID)) + flags |= PxContactPairFlag::eREMOVED_SHAPE_1; + + csp.flags = flags; + } +} + + +PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockCount(PxU32 extraDataSize_) +{ + PxU32 nbBlocks; + if (extraDataSize_ & ((1 << sExtraDataBlockSizePow2) - 1)) // not a multiple of block size -> need one block more + nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2) + 1; + else + nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2); + + return nbBlocks; +} + + +PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockSize(PxU32 extraDataSize_) +{ + return (computeExtraDataBlockCount(extraDataSize_) << sExtraDataBlockSizePow2); +} + + +PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader) +{ + PX_ASSERT(extraDataFlags); + + PxU16 extraDataSize_ = sizeof(PxContactPairIndex); + if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY) + extraDataSize_ += sizeof(PxContactPairVelocity); + if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY) + extraDataSize_ += sizeof(PxContactPairVelocity); + if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE) + extraDataSize_ += sizeof(PxContactPairPose); + if (addHeader) + extraDataSize_ += sizeof(ContactStreamHeader); + return extraDataSize_; +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairVelocity* cpVel, PxU32 index, const RigidSim& rs, bool isCCDPass) +{ + if (rs.getActorType() != PxActorType::eRIGID_STATIC) + { + const BodySim& bs = static_cast<const BodySim&>(rs); + if ((!isCCDPass) || (cpVel->type == PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY)) + { + const BodyCore& bc = bs.getBodyCore(); + cpVel->linearVelocity[index] = bc.getLinearVelocity(); + cpVel->angularVelocity[index] = bc.getAngularVelocity(); + } + else + { + PX_ASSERT(cpVel->type == PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY); + const Cm::SpatialVector& vel = bs.getLowLevelBody().getPreSolverVelocities(); + cpVel->linearVelocity[index] = vel.linear; + cpVel->angularVelocity[index] = vel.angular; + } + } + else + { + cpVel->linearVelocity[index] = PxVec3(0.0f); + cpVel->angularVelocity[index] = PxVec3(0.0f); + } +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairPose* cpPose, PxU32 index, const RigidSim& rs, bool isCCDPass, const bool useCurrentTransform) +{ + if (rs.getActorType() != PxActorType::eRIGID_STATIC) + { + const BodySim& bs = static_cast<const BodySim&>(rs); + const BodyCore& bc = bs.getBodyCore(); + + if (!isCCDPass) + { + if (useCurrentTransform) + cpPose->globalPose[index] = bc.getBody2World() * bc.getBody2Actor().getInverse(); + else + cpPose->globalPose[index] = bs.getLowLevelBody().getLastCCDTransform() * bc.getBody2Actor().getInverse(); + } + else + cpPose->globalPose[index] = bs.getLowLevelBody().getLastCCDTransform() * bc.getBody2Actor().getInverse(); + + } + else + { + const StaticSim& ss = static_cast<const StaticSim&>(rs); + const StaticCore& sc = ss.getStaticCore(); + cpPose->globalPose[index] = sc.getActor2World(); + } +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const RigidSim& rs0, const RigidSim& rs1, PxU32 ccdPass, const bool useCurrentTransform, + PxU32 pairIndex, PxU32 sizeOffset) +{ + ContactStreamHeader* strHeader = reinterpret_cast<ContactStreamHeader*>(stream); + strHeader->contactPass = Ps::to16(ccdPass); + + stream += sizeOffset; + PxU8* edStream = stream; + bool isCCDPass = (ccdPass != 0); + + { + PxContactPairIndex* cpIndex = reinterpret_cast<PxContactPairIndex*>(edStream); + cpIndex->type = PxContactPairExtraDataType::eCONTACT_PAIR_INDEX; + cpIndex->index = Ps::to16(pairIndex); + edStream += sizeof(PxContactPairIndex); + + PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream))); + } + + // Important: make sure this one is the first after the PxContactPairIndex item for discrete contacts as it needs to get filled in before the reports get sent + // (post solver velocity is not available when it gets created) + if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY) + { + PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream); + cpVel->type = PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY; + edStream += sizeof(PxContactPairVelocity); + + if (!isCCDPass) + raiseFlags(ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY); // don't know the post solver velocity yet + else + { + ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, true); + ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, true); + } + + PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream))); + } + if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY) + { + PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream); + cpVel->type = PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY; + ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, isCCDPass); + ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, isCCDPass); + edStream += sizeof(PxContactPairVelocity); + + PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream))); + } + if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE) + { + PxContactPairPose* cpPose = reinterpret_cast<PxContactPairPose*>(edStream); + cpPose->type = PxContactPairExtraDataType::eCONTACT_EVENT_POSE; + ContactStreamManager::fillInContactReportExtraData(cpPose, 0, rs0, isCCDPass, useCurrentTransform); + ContactStreamManager::fillInContactReportExtraData(cpPose, 1, rs1, isCCDPass, useCurrentTransform); + edStream += sizeof(PxContactPairPose); + + PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream))); + } + + extraDataSize = Ps::to16(sizeOffset + PxU32(edStream - stream)); +} + + +PX_FORCE_INLINE void Sc::ContactStreamManager::setContactReportPostSolverVelocity(PxU8* stream, const RigidSim& rs0, const RigidSim& rs1) +{ + PX_ASSERT(extraDataSize > (sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex))); + PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(stream + sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex)); + PX_ASSERT(cpVel->type == PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY); + + fillInContactReportExtraData(cpVel, 0, rs0, false); + fillInContactReportExtraData(cpVel, 1, rs1, false); + + clearFlags(ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY); +} + + +} + +#endif |