2023-08-11 10:55:58 +08:00
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2023 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_CONTACT_H
# define PX_CONTACT_H
/** \addtogroup physics
@ {
*/
# include "foundation/PxVec3.h"
# include "foundation/PxAssert.h"
# include "PxNodeIndex.h"
# if !PX_DOXYGEN
namespace physx
{
# endif
# if PX_VC
# pragma warning(push)
# pragma warning(disable: 4324) // Padding was added at the end of a structure because of a __declspec(align) value.
# endif
# define PXC_CONTACT_NO_FACE_INDEX 0xffffffff
class PxActor ;
2023-08-22 18:25:34 +08:00
/**
\ brief Struct for specifying mass modification for a pair of rigids
\ deprecated Use # PxConstraintInvMassScale instead . Deprecated since PhysX version 5.1 .
*/
PX_ALIGN_PREFIX ( 16 )
struct PX_DEPRECATED PxMassModificationProps
{
PxReal mInvMassScale0 ;
PxReal mInvInertiaScale0 ;
PxReal mInvMassScale1 ;
PxReal mInvInertiaScale1 ;
}
PX_ALIGN_SUFFIX ( 16 ) ;
2023-08-11 10:55:58 +08:00
/**
\ brief Header for a contact patch where all points share same material and normal
*/
PX_ALIGN_PREFIX ( 16 )
struct PxContactPatch
{
enum PxContactPatchFlags
{
eHAS_FACE_INDICES = 1 , //!< Indicates this contact stream has face indices.
eMODIFIABLE = 2 , //!< Indicates this contact stream is modifiable.
eFORCE_NO_RESPONSE = 4 , //!< Indicates this contact stream is notify-only (no contact response).
eHAS_MODIFIED_MASS_RATIOS = 8 , //!< Indicates this contact stream has modified mass ratios
eHAS_TARGET_VELOCITY = 16 , //!< Indicates this contact stream has target velocities set
eHAS_MAX_IMPULSE = 32 , //!< Indicates this contact stream has max impulses set
eREGENERATE_PATCHES = 64 , //!< Indicates this contact stream needs patches re-generated. This is required if the application modified either the contact normal or the material properties
eCOMPRESSED_MODIFIED_CONTACT = 128
} ;
/**
\ brief Modifiers for scaling the inertia of the involved bodies
*/
2023-08-22 18:25:34 +08:00
PX_ALIGN ( 16 , PxMassModificationProps mMassModification ) ; //16
2023-08-11 10:55:58 +08:00
/**
\ brief Contact normal
*/
PX_ALIGN ( 16 , PxVec3 normal ) ; //28
/**
\ brief Restitution coefficient
*/
PxReal restitution ; //32
/**
\ brief Dynamic friction coefficient
*/
PxReal dynamicFriction ; //36
/**
\ brief Static friction coefficient
*/
PxReal staticFriction ; //40
/**
\ brief Damping coefficient ( for compliant contacts )
*/
PxReal damping ; //44
/**
\ brief Index of the first contact in the patch
*/
PxU16 startContactIndex ; //46
/**
\ brief The number of contacts in this patch
*/
PxU8 nbContacts ; //47 //Can be a U8
/**
\ brief The combined material flag of two actors that come in contact
@ see PxMaterialFlag , PxCombineMode
*/
PxU8 materialFlags ; //48 //Can be a U16
/**
\ brief The PxContactPatchFlags for this patch
*/
PxU16 internalFlags ; //50 //Can be a U16
/**
\ brief Material index of first body
*/
PxU16 materialIndex0 ; //52 //Can be a U16
/**
\ brief Material index of second body
*/
PxU16 materialIndex1 ; //54 //Can be a U16
PxU16 pad [ 5 ] ; //64
}
PX_ALIGN_SUFFIX ( 16 ) ;
/**
\ brief Contact point data
*/
PX_ALIGN_PREFIX ( 16 )
struct PxContact
{
/**
\ brief Contact point in world space
*/
PxVec3 contact ; //12
/**
\ brief Separation value ( negative implies penetration ) .
*/
PxReal separation ; //16
}
PX_ALIGN_SUFFIX ( 16 ) ;
/**
\ brief Contact point data with additional target and max impulse values
*/
PX_ALIGN_PREFIX ( 16 )
struct PxExtendedContact : public PxContact
{
/**
\ brief Target velocity
*/
PX_ALIGN ( 16 , PxVec3 targetVelocity ) ; //28
/**
\ brief Maximum impulse
*/
PxReal maxImpulse ; //32
}
PX_ALIGN_SUFFIX ( 16 ) ;
/**
\ brief A modifiable contact point . This has additional fields per - contact to permit modification by user .
\ note Not all fields are currently exposed to the user .
*/
PX_ALIGN_PREFIX ( 16 )
struct PxModifiableContact : public PxExtendedContact
{
/**
\ brief Contact normal
*/
PX_ALIGN ( 16 , PxVec3 normal ) ; //44
/**
\ brief Restitution coefficient
*/
PxReal restitution ; //48
/**
\ brief Material Flags
*/
PxU32 materialFlags ; //52
/**
\ brief Shape A ' s material index
*/
PxU16 materialIndex0 ; //54
/**
\ brief Shape B ' s material index
*/
PxU16 materialIndex1 ; //56
/**
\ brief static friction coefficient
*/
PxReal staticFriction ; //60
/**
\ brief dynamic friction coefficient
*/
PxReal dynamicFriction ; //64
}
PX_ALIGN_SUFFIX ( 16 ) ;
/**
\ brief A class to iterate over a compressed contact stream . This supports read - only access to the various contact formats .
*/
struct PxContactStreamIterator
{
enum StreamFormat
{
eSIMPLE_STREAM ,
eMODIFIABLE_STREAM ,
eCOMPRESSED_MODIFIABLE_STREAM
} ;
/**
\ brief Utility zero vector to optimize functions returning zero vectors when a certain flag isn ' t set .
\ note This allows us to return by reference instead of having to return by value . Returning by value will go via memory ( registers - > stack - > registers ) , which can
cause performance issues on certain platforms .
*/
PxVec3 zero ;
/**
\ brief The patch headers .
*/
const PxContactPatch * patch ;
/**
\ brief The contacts
*/
const PxContact * contact ;
/**
\ brief The contact triangle face index
*/
const PxU32 * faceIndice ;
/**
\ brief The total number of patches in this contact stream
*/
PxU32 totalPatches ;
/**
\ brief The total number of contact points in this stream
*/
PxU32 totalContacts ;
/**
\ brief The current contact index
*/
PxU32 nextContactIndex ;
/**
\ brief The current patch Index
*/
PxU32 nextPatchIndex ;
/**
\ brief Size of contact patch header
\ note This varies whether the patch is modifiable or not .
*/
PxU32 contactPatchHeaderSize ;
/**
\ brief Contact point size
\ note This varies whether the patch has feature indices or is modifiable .
*/
PxU32 contactPointSize ;
/**
\ brief The stream format
*/
StreamFormat mStreamFormat ;
/**
\ brief Indicates whether this stream is notify - only or not .
*/
PxU32 forceNoResponse ;
/**
\ brief Internal helper for stepping the contact stream iterator
*/
bool pointStepped ;
/**
\ brief Specifies if this contactPatch has face indices ( handled as bool )
@ see faceIndice
*/
PxU32 hasFaceIndices ;
/**
\ brief Constructor
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxContactStreamIterator ( const PxU8 * contactPatches , const PxU8 * contactPoints , const PxU32 * contactFaceIndices , PxU32 nbPatches , PxU32 nbContacts )
: zero ( 0.f )
{
bool modify = false ;
bool compressedModify = false ;
bool response = false ;
bool indices = false ;
PxU32 pointSize = 0 ;
PxU32 patchHeaderSize = sizeof ( PxContactPatch ) ;
const PxContactPatch * patches = reinterpret_cast < const PxContactPatch * > ( contactPatches ) ;
if ( patches )
{
modify = ( patches - > internalFlags & PxContactPatch : : eMODIFIABLE ) ! = 0 ;
compressedModify = ( patches - > internalFlags & PxContactPatch : : eCOMPRESSED_MODIFIED_CONTACT ) ! = 0 ;
indices = ( patches - > internalFlags & PxContactPatch : : eHAS_FACE_INDICES ) ! = 0 ;
patch = patches ;
contact = reinterpret_cast < const PxContact * > ( contactPoints ) ;
faceIndice = contactFaceIndices ;
pointSize = compressedModify ? sizeof ( PxExtendedContact ) : modify ? sizeof ( PxModifiableContact ) : sizeof ( PxContact ) ;
response = ( patch - > internalFlags & PxContactPatch : : eFORCE_NO_RESPONSE ) = = 0 ;
}
mStreamFormat = compressedModify ? eCOMPRESSED_MODIFIABLE_STREAM : modify ? eMODIFIABLE_STREAM : eSIMPLE_STREAM ;
hasFaceIndices = PxU32 ( indices ) ;
forceNoResponse = PxU32 ( ! response ) ;
contactPatchHeaderSize = patchHeaderSize ;
contactPointSize = pointSize ;
nextPatchIndex = 0 ;
nextContactIndex = 0 ;
totalContacts = nbContacts ;
totalPatches = nbPatches ;
pointStepped = false ;
}
/**
\ brief Returns whether there are more patches in this stream .
\ return Whether there are more patches in this stream .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextPatch ( ) const
{
return nextPatchIndex < totalPatches ;
}
/**
\ brief Returns the total contact count .
\ return Total contact count .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalContactCount ( ) const
{
return totalContacts ;
}
/**
\ brief Returns the total patch count .
\ return Total patch count .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalPatchCount ( ) const
{
return totalPatches ;
}
/**
\ brief Advances iterator to next contact patch .
*/
PX_CUDA_CALLABLE PX_INLINE void nextPatch ( )
{
PX_ASSERT ( nextPatchIndex < totalPatches ) ;
if ( nextPatchIndex )
{
if ( nextContactIndex < patch - > nbContacts )
{
PxU32 nbToStep = patch - > nbContacts - this - > nextContactIndex ;
contact = reinterpret_cast < const PxContact * > ( reinterpret_cast < const PxU8 * > ( contact ) + contactPointSize * nbToStep ) ;
}
patch = reinterpret_cast < const PxContactPatch * > ( reinterpret_cast < const PxU8 * > ( patch ) + contactPatchHeaderSize ) ;
}
nextPatchIndex + + ;
nextContactIndex = 0 ;
}
/**
\ brief Returns if the current patch has more contacts .
\ return If there are more contacts in the current patch .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextContact ( ) const
{
return nextContactIndex < ( patch - > nbContacts ) ;
}
/**
\ brief Advances to the next contact in the patch .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE void nextContact ( )
{
PX_ASSERT ( nextContactIndex < patch - > nbContacts ) ;
if ( pointStepped )
{
contact = reinterpret_cast < const PxContact * > ( reinterpret_cast < const PxU8 * > ( contact ) + contactPointSize ) ;
faceIndice + + ;
}
nextContactIndex + + ;
pointStepped = true ;
}
/**
\ brief Gets the current contact ' s normal
\ return The current contact ' s normal .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 & getContactNormal ( ) const
{
return getContactPatch ( ) . normal ;
}
/**
\ brief Gets the inverse mass scale for body 0.
\ return The inverse mass scale for body 0.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale0 ( ) const
{
2023-08-22 18:25:34 +08:00
return patch - > mMassModification . mInvMassScale0 ;
2023-08-11 10:55:58 +08:00
}
/**
\ brief Gets the inverse mass scale for body 1.
\ return The inverse mass scale for body 1.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale1 ( ) const
{
2023-08-22 18:25:34 +08:00
return patch - > mMassModification . mInvMassScale1 ;
2023-08-11 10:55:58 +08:00
}
/**
\ brief Gets the inverse inertia scale for body 0.
\ return The inverse inertia scale for body 0.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale0 ( ) const
{
2023-08-22 18:25:34 +08:00
return patch - > mMassModification . mInvInertiaScale0 ;
2023-08-11 10:55:58 +08:00
}
/**
\ brief Gets the inverse inertia scale for body 1.
\ return The inverse inertia scale for body 1.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale1 ( ) const
{
2023-08-22 18:25:34 +08:00
return patch - > mMassModification . mInvInertiaScale1 ;
2023-08-11 10:55:58 +08:00
}
/**
\ brief Gets the contact ' s max impulse .
\ return The contact ' s max impulse .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getMaxImpulse ( ) const
{
return mStreamFormat ! = eSIMPLE_STREAM ? getExtendedContact ( ) . maxImpulse : PX_MAX_REAL ;
}
/**
\ brief Gets the contact ' s target velocity .
\ return The contact ' s target velocity .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 & getTargetVel ( ) const
{
return mStreamFormat ! = eSIMPLE_STREAM ? getExtendedContact ( ) . targetVelocity : zero ;
}
/**
\ brief Gets the contact ' s contact point .
\ return The contact ' s contact point .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 & getContactPoint ( ) const
{
return contact - > contact ;
}
/**
\ brief Gets the contact ' s separation .
\ return The contact ' s separation .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getSeparation ( ) const
{
return contact - > separation ;
}
/**
\ brief Gets the contact ' s face index for shape 0.
\ return The contact ' s face index for shape 0.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex0 ( ) const
{
return PXC_CONTACT_NO_FACE_INDEX ;
}
/**
\ brief Gets the contact ' s face index for shape 1.
\ return The contact ' s face index for shape 1.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex1 ( ) const
{
return hasFaceIndices ? * faceIndice : PXC_CONTACT_NO_FACE_INDEX ;
}
/**
\ brief Gets the contact ' s static friction coefficient .
\ return The contact ' s static friction coefficient .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getStaticFriction ( ) const
{
return getContactPatch ( ) . staticFriction ;
}
/**
\ brief Gets the contact ' s dynamic friction coefficient .
\ return The contact ' s dynamic friction coefficient .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDynamicFriction ( ) const
{
return getContactPatch ( ) . dynamicFriction ;
}
/**
\ brief Gets the contact ' s restitution coefficient .
\ return The contact ' s restitution coefficient .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getRestitution ( ) const
{
return getContactPatch ( ) . restitution ;
}
/**
\ brief Gets the contact ' s damping value .
\ return The contact ' s damping value .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDamping ( ) const
{
return getContactPatch ( ) . damping ;
}
/**
\ brief Gets the contact ' s material flags .
\ return The contact ' s material flags .
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getMaterialFlags ( ) const
{
return getContactPatch ( ) . materialFlags ;
}
/**
\ brief Gets the contact ' s material index for shape 0.
\ return The contact ' s material index for shape 0.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex0 ( ) const
{
return PxU16 ( getContactPatch ( ) . materialIndex0 ) ;
}
/**
\ brief Gets the contact ' s material index for shape 1.
\ return The contact ' s material index for shape 1.
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex1 ( ) const
{
return PxU16 ( getContactPatch ( ) . materialIndex1 ) ;
}
/**
\ brief Advances the contact stream iterator to a specific contact index .
\ return True if advancing was possible
*/
bool advanceToIndex ( const PxU32 initialIndex )
{
PX_ASSERT ( this - > nextPatchIndex = = 0 & & this - > nextContactIndex = = 0 ) ;
PxU32 numToAdvance = initialIndex ;
if ( numToAdvance = = 0 )
{
PX_ASSERT ( hasNextPatch ( ) ) ;
nextPatch ( ) ;
return true ;
}
while ( numToAdvance )
{
while ( hasNextPatch ( ) )
{
nextPatch ( ) ;
PxU32 patchSize = patch - > nbContacts ;
if ( numToAdvance < = patchSize )
{
contact = reinterpret_cast < const PxContact * > ( reinterpret_cast < const PxU8 * > ( contact ) + contactPointSize * numToAdvance ) ;
nextContactIndex + = numToAdvance ;
return true ;
}
else
{
numToAdvance - = patchSize ;
}
}
}
return false ;
}
private :
/**
\ brief Internal helper
*/
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxContactPatch & getContactPatch ( ) const
{
return * static_cast < const PxContactPatch * > ( patch ) ;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxExtendedContact & getExtendedContact ( ) const
{
PX_ASSERT ( mStreamFormat = = eMODIFIABLE_STREAM | | mStreamFormat = = eCOMPRESSED_MODIFIABLE_STREAM ) ;
return * static_cast < const PxExtendedContact * > ( contact ) ;
}
} ;
/**
\ brief Contains contact information for a contact reported by the direct - GPU contact report API . See PxScene : : copyContactData ( ) .
*/
struct PxGpuContactPair
{
PxU8 * contactPatches ; //!< Ptr to contact patches. Type: PxContactPatch*, size: nbPatches.
PxU8 * contactPoints ; //!< Ptr to contact points. Type: PxContact*, size: nbContacts.
PxReal * contactForces ; //!< Ptr to contact forces. Size: nbContacts.
PxU32 transformCacheRef0 ; //!< Ref to shape0's transform in transform cache.
PxU32 transformCacheRef1 ; //!< Ref to shape1's transform in transform cache.
PxNodeIndex nodeIndex0 ; //!< Unique Id for actor0 if the actor is dynamic.
PxNodeIndex nodeIndex1 ; //!< Unique Id for actor1 if the actor is dynamic.
PxActor * actor0 ; //!< Ptr to PxActor for actor0.
PxActor * actor1 ; //!< Ptr to PxActor for actor1.
PxU16 nbContacts ; //!< Num contacts.
PxU16 nbPatches ; //!< Num patches.
} ;
# if PX_VC
# pragma warning(pop)
# endif
# if !PX_DOXYGEN
} // namespace physx
# endif
/** @} */
# endif