Space-Project/dependencies/physx-4.1/include/PxContact.h
2021-01-16 17:11:39 +01:00

584 lines
15 KiB
C++

//
// 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-2019 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"
#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
PX_ALIGN_PREFIX(16)
struct PxMassModificationProps
{
PxReal mInvMassScale0;
PxReal mInvInertiaScale0;
PxReal mInvMassScale1;
PxReal mInvInertiaScale1;
}
PX_ALIGN_SUFFIX(16);
/**
\brief Header for 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
};
PX_ALIGN(16, PxMassModificationProps mMassModification); //16
/**
\brief Contact normal
*/
PX_ALIGN(16, PxVec3 normal); //28
/**
\brief Restitution coefficient
*/
PxReal restitution; //32
PxReal dynamicFriction; //36
PxReal staticFriction; //40
PxU8 startContactIndex; //41
PxU8 nbContacts; //42 //Can be a U8
PxU8 materialFlags; //43 //Can be a U16
PxU8 internalFlags; //44 //Can be a U16
PxU16 materialIndex0; //46 //Can be a U16
PxU16 materialIndex1; //48 //Can be a U16
}
PX_ALIGN_SUFFIX(16);
/**
\brief Contact point data including face (feature) indices
*/
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);
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;
bool pointStepped;
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;
}
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
{
return patch->mMassModification.mInvMassScale0;
}
/**
\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
{
return patch->mMassModification.mInvMassScale1;
}
/**
\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
{
return patch->mMassModification.mInvInertiaScale0;
}
/**
\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
{
return patch->mMassModification.mInvInertiaScale1;
}
/**
\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 static dynamic coefficient.
\return The contact's static dynamic 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 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.
*/
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);
}
};
#if PX_VC
#pragma warning(pop)
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif