584 lines
15 KiB
C
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
|