487 lines
16 KiB
C++
487 lines
16 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_MODIFY_CALLBACK
|
|
#define PX_CONTACT_MODIFY_CALLBACK
|
|
/** \addtogroup physics
|
|
@{
|
|
*/
|
|
|
|
#include "PxPhysXConfig.h"
|
|
#include "PxShape.h"
|
|
#include "PxContact.h"
|
|
#include "foundation/PxTransform.h"
|
|
|
|
#if !PX_DOXYGEN
|
|
namespace physx
|
|
{
|
|
#endif
|
|
|
|
class PxShape;
|
|
|
|
/**
|
|
\brief An array of contact points, as passed to contact modification.
|
|
|
|
The word 'set' in the name does not imply that duplicates are filtered in any
|
|
way. This initial set of contacts does potentially get reduced to a smaller
|
|
set before being passed to the solver.
|
|
|
|
You can use the accessors to read and write contact properties. The number of
|
|
contacts is immutable, other than being able to disable contacts using ignore().
|
|
|
|
@see PxContactModifyCallback, PxModifiableContact
|
|
*/
|
|
class PxContactSet
|
|
{
|
|
public:
|
|
/**
|
|
\brief Get the position of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.point
|
|
*/
|
|
PX_FORCE_INLINE const PxVec3& getPoint(PxU32 i) const { return mContacts[i].contact; }
|
|
|
|
/**
|
|
\brief Alter the position of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.point
|
|
*/
|
|
PX_FORCE_INLINE void setPoint(PxU32 i, const PxVec3& p) { mContacts[i].contact = p; }
|
|
|
|
/**
|
|
\brief Get the contact normal of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.normal
|
|
*/
|
|
PX_FORCE_INLINE const PxVec3& getNormal(PxU32 i) const { return mContacts[i].normal; }
|
|
|
|
/**
|
|
\brief Alter the contact normal of a specific contact point in the set.
|
|
|
|
\note Changing the normal can cause contact points to be ignored.
|
|
|
|
@see PxModifiableContact.normal
|
|
*/
|
|
PX_FORCE_INLINE void setNormal(PxU32 i, const PxVec3& n)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES;
|
|
mContacts[i].normal = n;
|
|
}
|
|
|
|
/**
|
|
\brief Get the separation of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.separation
|
|
*/
|
|
PX_FORCE_INLINE PxReal getSeparation(PxU32 i) const { return mContacts[i].separation; }
|
|
|
|
/**
|
|
\brief Alter the separation of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.separation
|
|
*/
|
|
PX_FORCE_INLINE void setSeparation(PxU32 i, PxReal s) { mContacts[i].separation = s; }
|
|
|
|
/**
|
|
\brief Get the target velocity of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.targetVelocity
|
|
|
|
*/
|
|
PX_FORCE_INLINE const PxVec3& getTargetVelocity(PxU32 i) const { return mContacts[i].targetVelocity; }
|
|
|
|
/**
|
|
\brief Alter the target velocity of a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.targetVelocity
|
|
*/
|
|
PX_FORCE_INLINE void setTargetVelocity(PxU32 i, const PxVec3& v)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eHAS_TARGET_VELOCITY;
|
|
mContacts[i].targetVelocity = v;
|
|
}
|
|
|
|
/**
|
|
\brief Get the face index with respect to the first shape of the pair for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.internalFaceIndex0
|
|
*/
|
|
PX_FORCE_INLINE PxU32 getInternalFaceIndex0(PxU32 i) { PX_UNUSED(i); return PXC_CONTACT_NO_FACE_INDEX; }
|
|
|
|
/**
|
|
\brief Get the face index with respect to the second shape of the pair for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.internalFaceIndex1
|
|
*/
|
|
PX_FORCE_INLINE PxU32 getInternalFaceIndex1(PxU32 i)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
if (patch->internalFlags & PxContactPatch::eHAS_FACE_INDICES)
|
|
{
|
|
return reinterpret_cast<PxU32*>(mContacts + mCount)[mCount + i];
|
|
}
|
|
return PXC_CONTACT_NO_FACE_INDEX;
|
|
}
|
|
|
|
/**
|
|
\brief Get the maximum impulse for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.maxImpulse
|
|
*/
|
|
PX_FORCE_INLINE PxReal getMaxImpulse(PxU32 i) const { return mContacts[i].maxImpulse; }
|
|
|
|
/**
|
|
\brief Alter the maximum impulse for a specific contact point in the set.
|
|
|
|
\note Must be nonnegative. If set to zero, the contact point will be ignored
|
|
|
|
@see PxModifiableContact.maxImpulse
|
|
*/
|
|
PX_FORCE_INLINE void setMaxImpulse(PxU32 i, PxReal s)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eHAS_MAX_IMPULSE;
|
|
mContacts[i].maxImpulse = s;
|
|
}
|
|
|
|
/**
|
|
\brief Get the restitution coefficient for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.restitution
|
|
*/
|
|
PX_FORCE_INLINE PxReal getRestitution(PxU32 i) const { return mContacts[i].restitution; }
|
|
|
|
/**
|
|
\brief Alter the restitution coefficient for a specific contact point in the set.
|
|
|
|
\note Valid ranges [0,1]
|
|
|
|
@see PxModifiableContact.restitution
|
|
*/
|
|
PX_FORCE_INLINE void setRestitution(PxU32 i, PxReal r)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES;
|
|
mContacts[i].restitution = r;
|
|
}
|
|
|
|
/**
|
|
\brief Get the static friction coefficient for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.staticFriction
|
|
*/
|
|
PX_FORCE_INLINE PxReal getStaticFriction(PxU32 i) const { return mContacts[i].staticFriction; }
|
|
|
|
/**
|
|
\brief Alter the static friction coefficient for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.staticFriction
|
|
*/
|
|
PX_FORCE_INLINE void setStaticFriction(PxU32 i, PxReal f)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES;
|
|
mContacts[i].staticFriction = f;
|
|
}
|
|
|
|
/**
|
|
\brief Get the static friction coefficient for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.dynamicFriction
|
|
*/
|
|
PX_FORCE_INLINE PxReal getDynamicFriction(PxU32 i) const { return mContacts[i].dynamicFriction; }
|
|
|
|
/**
|
|
\brief Alter the static dynamic coefficient for a specific contact point in the set.
|
|
|
|
@see PxModifiableContact.dynamic
|
|
*/
|
|
PX_FORCE_INLINE void setDynamicFriction(PxU32 i, PxReal f)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES;
|
|
mContacts[i].dynamicFriction = f;
|
|
}
|
|
|
|
/**
|
|
\brief Ignore the contact point.
|
|
|
|
If a contact point is ignored then no force will get applied at this point. This can be used to disable collision in certain areas of a shape, for example.
|
|
*/
|
|
PX_FORCE_INLINE void ignore(PxU32 i) { mContacts[i].maxImpulse = 0.f; }
|
|
|
|
/**
|
|
\brief The number of contact points in the set.
|
|
*/
|
|
PX_FORCE_INLINE PxU32 size() const { return mCount; }
|
|
|
|
/**
|
|
\brief Returns the invMassScale of body 0
|
|
|
|
A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact
|
|
treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass.
|
|
*/
|
|
PX_FORCE_INLINE PxReal getInvMassScale0() const
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
return patch->mMassModification.mInvMassScale0;
|
|
}
|
|
|
|
/**
|
|
\brief Returns the invMassScale of body 1
|
|
|
|
A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact
|
|
treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass.
|
|
*/
|
|
PX_FORCE_INLINE PxReal getInvMassScale1() const
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
return patch->mMassModification.mInvMassScale1;
|
|
}
|
|
|
|
/**
|
|
\brief Returns the invInertiaScale of body 0
|
|
|
|
A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact
|
|
treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia.
|
|
*/
|
|
PX_FORCE_INLINE PxReal getInvInertiaScale0() const
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
return patch->mMassModification.mInvInertiaScale0;
|
|
}
|
|
|
|
/**
|
|
\brief Returns the invInertiaScale of body 1
|
|
|
|
A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact
|
|
treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia.
|
|
*/
|
|
PX_FORCE_INLINE PxReal getInvInertiaScale1() const
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
return patch->mMassModification.mInvInertiaScale1;
|
|
}
|
|
|
|
/**
|
|
\brief Sets the invMassScale of body 0
|
|
|
|
This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact
|
|
treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass.
|
|
*/
|
|
PX_FORCE_INLINE void setInvMassScale0(const PxReal scale)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->mMassModification.mInvMassScale0 = scale;
|
|
patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS;
|
|
}
|
|
|
|
/**
|
|
\brief Sets the invMassScale of body 1
|
|
|
|
This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact
|
|
treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass.
|
|
*/
|
|
PX_FORCE_INLINE void setInvMassScale1(const PxReal scale)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->mMassModification.mInvMassScale1 = scale;
|
|
patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS;
|
|
}
|
|
|
|
/**
|
|
\brief Sets the invInertiaScale of body 0
|
|
|
|
This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact
|
|
treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia.
|
|
*/
|
|
PX_FORCE_INLINE void setInvInertiaScale0(const PxReal scale)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->mMassModification.mInvInertiaScale0 = scale;
|
|
patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS;
|
|
}
|
|
|
|
/**
|
|
\brief Sets the invInertiaScale of body 1
|
|
|
|
This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact
|
|
treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia.
|
|
*/
|
|
PX_FORCE_INLINE void setInvInertiaScale1(const PxReal scale)
|
|
{
|
|
PxContactPatch* patch = getPatch();
|
|
patch->mMassModification.mInvInertiaScale1 = scale;
|
|
patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS;
|
|
}
|
|
|
|
protected:
|
|
|
|
PX_FORCE_INLINE PxContactPatch* getPatch() const
|
|
{
|
|
const size_t headerOffset = sizeof(PxContactPatch)*mCount;
|
|
return reinterpret_cast<PxContactPatch*>(reinterpret_cast<PxU8*>(mContacts) - headerOffset);
|
|
}
|
|
|
|
PxU32 mCount; //!< Number of contact points in the set
|
|
PxModifiableContact* mContacts; //!< The contact points of the set
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
\brief An array of instances of this class is passed to PxContactModifyCallback::onContactModify().
|
|
|
|
@see PxContactModifyCallback
|
|
*/
|
|
|
|
class PxContactModifyPair
|
|
{
|
|
public:
|
|
|
|
/**
|
|
\brief The actors which make up the pair in contact.
|
|
|
|
Note that these are the actors as seen by the simulation, and may have been deleted since the simulation step started.
|
|
*/
|
|
|
|
const PxRigidActor* actor[2];
|
|
/**
|
|
\brief The shapes which make up the pair in contact.
|
|
|
|
Note that these are the shapes as seen by the simulation, and may have been deleted since the simulation step started.
|
|
*/
|
|
|
|
const PxShape* shape[2];
|
|
|
|
/**
|
|
\brief The shape to world transforms of the two shapes.
|
|
|
|
These are the transforms as the simulation engine sees them, and may have been modified by the application
|
|
since the simulation step started.
|
|
|
|
*/
|
|
|
|
PxTransform transform[2];
|
|
|
|
/**
|
|
\brief An array of contact points between these two shapes.
|
|
*/
|
|
|
|
PxContactSet contacts;
|
|
};
|
|
|
|
|
|
/**
|
|
\brief An interface class that the user can implement in order to modify contact constraints.
|
|
|
|
<b>Threading:</b> It is <b>necessary</b> to make this class thread safe as it will be called in the context of the
|
|
simulation thread. It might also be necessary to make it reentrant, since some calls can be made by multi-threaded
|
|
parts of the physics engine.
|
|
|
|
You can enable the use of this contact modification callback by raising the flag PxPairFlag::eMODIFY_CONTACTS in
|
|
the filter shader/callback (see #PxSimulationFilterShader) for a pair of rigid body objects.
|
|
|
|
Please note:
|
|
+ Raising the contact modification flag will not wake the actors up automatically.
|
|
+ It is not possible to turn off the performance degradation by simply removing the callback from the scene, the
|
|
filter shader/callback has to be used to clear the contact modification flag.
|
|
+ The contacts will only be reported as long as the actors are awake. There will be no callbacks while the actors are sleeping.
|
|
|
|
@see PxScene.setContactModifyCallback() PxScene.getContactModifyCallback()
|
|
*/
|
|
class PxContactModifyCallback
|
|
{
|
|
public:
|
|
|
|
/**
|
|
\brief Passes modifiable arrays of contacts to the application.
|
|
|
|
The initial contacts are as determined fresh each frame by collision detection.
|
|
|
|
The number of contacts can not be changed, so you cannot add your own contacts. You may however
|
|
disable contacts using PxContactSet::ignore().
|
|
|
|
@see PxContactModifyPair
|
|
*/
|
|
virtual void onContactModify(PxContactModifyPair* const pairs, PxU32 count) = 0;
|
|
|
|
protected:
|
|
virtual ~PxContactModifyCallback(){}
|
|
};
|
|
|
|
/**
|
|
\brief An interface class that the user can implement in order to modify CCD contact constraints.
|
|
|
|
<b>Threading:</b> It is <b>necessary</b> to make this class thread safe as it will be called in the context of the
|
|
simulation thread. It might also be necessary to make it reentrant, since some calls can be made by multi-threaded
|
|
parts of the physics engine.
|
|
|
|
You can enable the use of this contact modification callback by raising the flag PxPairFlag::eMODIFY_CONTACTS in
|
|
the filter shader/callback (see #PxSimulationFilterShader) for a pair of rigid body objects.
|
|
|
|
Please note:
|
|
+ Raising the contact modification flag will not wake the actors up automatically.
|
|
+ It is not possible to turn off the performance degradation by simply removing the callback from the scene, the
|
|
filter shader/callback has to be used to clear the contact modification flag.
|
|
+ The contacts will only be reported as long as the actors are awake. There will be no callbacks while the actors are sleeping.
|
|
|
|
@see PxScene.setContactModifyCallback() PxScene.getContactModifyCallback()
|
|
*/
|
|
class PxCCDContactModifyCallback
|
|
{
|
|
public:
|
|
|
|
/**
|
|
\brief Passes modifiable arrays of contacts to the application.
|
|
|
|
The initial contacts are as determined fresh each frame by collision detection.
|
|
|
|
The number of contacts can not be changed, so you cannot add your own contacts. You may however
|
|
disable contacts using PxContactSet::ignore().
|
|
|
|
@see PxContactModifyPair
|
|
*/
|
|
virtual void onCCDContactModify(PxContactModifyPair* const pairs, PxU32 count) = 0;
|
|
|
|
protected:
|
|
virtual ~PxCCDContactModifyCallback(){}
|
|
};
|
|
|
|
|
|
#if !PX_DOXYGEN
|
|
} // namespace physx
|
|
#endif
|
|
|
|
/** @} */
|
|
#endif
|