include/PxContact.h
File members: include/PxContact.h
// 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-2024 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
#include "foundation/PxVec3.h"
#include "foundation/PxAssert.h"
#include "PxConstraintDesc.h"
#include "PxNodeIndex.h"
#include "PxMaterial.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;
PX_ALIGN_PREFIX(16)
struct PxContactPatch
{
enum PxContactPatchFlags
{
eHAS_FACE_INDICES = 1,
eMODIFIABLE = 2,
eFORCE_NO_RESPONSE = 4,
eHAS_MODIFIED_MASS_RATIOS = 8,
eHAS_TARGET_VELOCITY = 16,
eHAS_MAX_IMPULSE = 32,
eREGENERATE_PATCHES = 64,
eCOMPRESSED_MODIFIED_CONTACT = 128
};
PX_ALIGN(16, PxConstraintInvMassScale mMassModification);
PX_ALIGN(16, PxVec3 normal);
PxReal restitution;
PxReal dynamicFriction;
PxReal staticFriction;
PxReal damping;
PxU16 startContactIndex;
PxU8 nbContacts;
PxU8 materialFlags;
PxU16 internalFlags;
PxU16 materialIndex0;
PxU16 materialIndex1;
PxU16 pad[5];
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxContact
{
PxVec3 contact;
PxReal separation;
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxExtendedContact : public PxContact
{
PX_ALIGN(16, PxVec3 targetVelocity);
PxReal maxImpulse;
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxModifiableContact : public PxExtendedContact
{
PX_ALIGN(16, PxVec3 normal);
PxReal restitution;
PxU32 materialFlags;
PxU16 materialIndex0;
PxU16 materialIndex1;
PxReal staticFriction;
PxReal dynamicFriction;
}
PX_ALIGN_SUFFIX(16);
struct PxContactStreamIterator
{
enum StreamFormat
{
eSIMPLE_STREAM,
eMODIFIABLE_STREAM,
eCOMPRESSED_MODIFIABLE_STREAM
};
PxVec3 zero;
const PxContactPatch* patch;
const PxContact* contact;
const PxU32* faceIndice;
PxU32 totalPatches;
PxU32 totalContacts;
PxU32 nextContactIndex;
PxU32 nextPatchIndex;
PxU32 contactPatchHeaderSize;
PxU32 contactPointSize;
StreamFormat mStreamFormat;
PxU32 forceNoResponse;
bool pointStepped;
PxU32 hasFaceIndices;
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;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextPatch() const
{
return nextPatchIndex < totalPatches;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalContactCount() const
{
return totalContacts;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalPatchCount() const
{
return totalPatches;
}
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;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextContact() const
{
return nextContactIndex < (patch->nbContacts);
}
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;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactNormal() const
{
return getContactPatch().normal;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale0() const
{
return patch->mMassModification.linear0;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale1() const
{
return patch->mMassModification.linear1;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale0() const
{
return patch->mMassModification.angular0;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale1() const
{
return patch->mMassModification.angular1;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getMaxImpulse() const
{
return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().maxImpulse : PX_MAX_REAL;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getTargetVel() const
{
return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().targetVelocity : zero;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactPoint() const
{
return contact->contact;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getSeparation() const
{
return contact->separation;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex0() const
{
return PXC_CONTACT_NO_FACE_INDEX;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex1() const
{
return hasFaceIndices ? *faceIndice : PXC_CONTACT_NO_FACE_INDEX;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getStaticFriction() const
{
return getContactPatch().staticFriction;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDynamicFriction() const
{
return getContactPatch().dynamicFriction;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getRestitution() const
{
return getContactPatch().restitution;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDamping() const
{
return getContactPatch().damping;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getMaterialFlags() const
{
return getContactPatch().materialFlags;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex0() const
{
return PxU16(getContactPatch().materialIndex0);
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex1() const
{
return PxU16(getContactPatch().materialIndex1);
}
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:
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);
}
};
struct PxFrictionPatch
{
static const PxU32 MAX_ANCHOR_COUNT = 2;
PxVec3 anchorPositions[MAX_ANCHOR_COUNT];
PxVec3 anchorImpulses[MAX_ANCHOR_COUNT];
PxU32 anchorCount;
};
class PxFrictionAnchorStreamIterator
{
public:
PX_CUDA_CALLABLE PX_FORCE_INLINE PxFrictionAnchorStreamIterator(const PxU8* contactPatches, const PxU8* frictionPatches, PxU32 patchCount)
:
mContactPatches(reinterpret_cast<const PxContactPatch*>(contactPatches)),
mFrictionPatches(reinterpret_cast<const PxFrictionPatch*>(frictionPatches)),
mPatchCount(patchCount),
mFrictionAnchorIndex(-1),
mPatchIndex(-1)
{}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextPatch() const
{
return isValid() && mPatchIndex < PxI32(mPatchCount) - 1;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE void nextPatch()
{
PX_ASSERT(hasNextPatch());
++mPatchIndex;
mFrictionAnchorIndex = -1;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextFrictionAnchor() const
{
return patchIsValid() && mFrictionAnchorIndex < PxI32(mFrictionPatches[mPatchIndex].anchorCount) - 1;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE void nextFrictionAnchor()
{
PX_ASSERT(hasNextFrictionAnchor());
mFrictionAnchorIndex++;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getPosition() const
{
PX_ASSERT(frictionAnchorIsValid());
return mFrictionPatches[mPatchIndex].anchorPositions[mFrictionAnchorIndex];
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getImpulse() const
{
PX_ASSERT(frictionAnchorIsValid());
return mFrictionPatches[mPatchIndex].anchorImpulses[mFrictionAnchorIndex];
}
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getNormal() const
{
PX_ASSERT(patchIsValid());
return mContactPatches[mPatchIndex].normal;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getStaticFriction() const
{
PX_ASSERT(patchIsValid());
return mContactPatches[mPatchIndex].staticFriction;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDynamicFriction() const
{
PX_ASSERT(patchIsValid());
return mContactPatches[mPatchIndex].dynamicFriction;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxMaterialFlags getMaterialFlags() const
{
PX_ASSERT(patchIsValid());
return PxMaterialFlags(mContactPatches[mPatchIndex].materialFlags);
}
private:
PX_CUDA_CALLABLE PX_FORCE_INLINE PxFrictionAnchorStreamIterator();
PX_CUDA_CALLABLE PX_FORCE_INLINE bool isValid() const
{
return mContactPatches && mFrictionPatches;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool patchIsValid() const
{
return isValid() && mPatchIndex >= 0 && mPatchIndex < PxI32(mPatchCount);
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool frictionAnchorIsValid() const
{
return patchIsValid() && mFrictionAnchorIndex >= 0 && mFrictionAnchorIndex < PxI32(mFrictionPatches[mPatchIndex].anchorCount);
}
const PxContactPatch* mContactPatches;
const PxFrictionPatch* mFrictionPatches;
PxU32 mPatchCount;
PxI32 mFrictionAnchorIndex;
PxI32 mPatchIndex;
};
struct PxGpuContactPair
{
PxU8* contactPatches;
PxU8* contactPoints;
PxReal* contactForces;
PxU8* frictionPatches;
PxU32 transformCacheRef0;
PxU32 transformCacheRef1;
PxNodeIndex nodeIndex0;
PxNodeIndex nodeIndex1;
PxActor* actor0;
PxActor* actor1;
PxU16 nbContacts;
PxU16 nbPatches;
};
#if PX_VC
#pragma warning(pop)
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif