645 lines
21 KiB
C
645 lines
21 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_PHYSICS_NP_RIGIDBODY_TEMPLATE
|
||
|
#define PX_PHYSICS_NP_RIGIDBODY_TEMPLATE
|
||
|
|
||
|
#include "NpRigidActorTemplate.h"
|
||
|
#include "ScbBody.h"
|
||
|
#include "NpPhysics.h"
|
||
|
#include "NpShape.h"
|
||
|
#include "NpScene.h"
|
||
|
|
||
|
namespace physx
|
||
|
{
|
||
|
|
||
|
PX_INLINE PxVec3 invertDiagInertia(const PxVec3& m)
|
||
|
{
|
||
|
return PxVec3( m.x == 0.0f ? 0.0f : 1.0f/m.x,
|
||
|
m.y == 0.0f ? 0.0f : 1.0f/m.y,
|
||
|
m.z == 0.0f ? 0.0f : 1.0f/m.z);
|
||
|
}
|
||
|
|
||
|
|
||
|
#if PX_ENABLE_DEBUG_VISUALIZATION
|
||
|
/*
|
||
|
given the diagonal of the body space inertia tensor, and the total mass
|
||
|
this returns the body space AABB width, height and depth of an equivalent box
|
||
|
*/
|
||
|
PX_INLINE PxVec3 getDimsFromBodyInertia(const PxVec3& inertiaMoments, PxReal mass)
|
||
|
{
|
||
|
const PxVec3 inertia = inertiaMoments * (6.0f/mass);
|
||
|
return PxVec3( PxSqrt(PxAbs(- inertia.x + inertia.y + inertia.z)),
|
||
|
PxSqrt(PxAbs(+ inertia.x - inertia.y + inertia.z)),
|
||
|
PxSqrt(PxAbs(+ inertia.x + inertia.y - inertia.z)));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
class NpRigidBodyTemplate : public NpRigidActorTemplate<APIClass>
|
||
|
{
|
||
|
private:
|
||
|
typedef NpRigidActorTemplate<APIClass> RigidActorTemplateClass;
|
||
|
public:
|
||
|
// PX_SERIALIZATION
|
||
|
NpRigidBodyTemplate(PxBaseFlags baseFlags) : RigidActorTemplateClass(baseFlags), mBody(PxEmpty) {}
|
||
|
//~PX_SERIALIZATION
|
||
|
virtual ~NpRigidBodyTemplate();
|
||
|
|
||
|
//---------------------------------------------------------------------------------
|
||
|
// PxRigidActor implementation
|
||
|
//---------------------------------------------------------------------------------
|
||
|
// The rule is: If an API method is used somewhere in here, it has to be redeclared, else GCC whines
|
||
|
virtual PxTransform getGlobalPose() const = 0;
|
||
|
|
||
|
//---------------------------------------------------------------------------------
|
||
|
// PxRigidBody implementation
|
||
|
//---------------------------------------------------------------------------------
|
||
|
|
||
|
// Center of mass pose
|
||
|
virtual PxTransform getCMassLocalPose() const;
|
||
|
|
||
|
// Mass
|
||
|
virtual void setMass(PxReal mass);
|
||
|
virtual PxReal getMass() const;
|
||
|
virtual PxReal getInvMass() const;
|
||
|
|
||
|
virtual void setMassSpaceInertiaTensor(const PxVec3& m);
|
||
|
virtual PxVec3 getMassSpaceInertiaTensor() const;
|
||
|
virtual PxVec3 getMassSpaceInvInertiaTensor() const;
|
||
|
|
||
|
// Velocity
|
||
|
virtual PxVec3 getLinearVelocity() const;
|
||
|
virtual PxVec3 getAngularVelocity() const;
|
||
|
|
||
|
virtual bool attachShape(PxShape& shape);
|
||
|
|
||
|
//---------------------------------------------------------------------------------
|
||
|
// Miscellaneous
|
||
|
//---------------------------------------------------------------------------------
|
||
|
NpRigidBodyTemplate(PxType concreteType, PxBaseFlags baseFlags, const PxActorType::Enum type, const PxTransform& bodyPose);
|
||
|
|
||
|
PX_FORCE_INLINE const Scb::Body& getScbBodyFast() const { return mBody; } // PT: important: keep returning an address here (else update prefetch in SceneQueryManager::addShapes)
|
||
|
PX_FORCE_INLINE Scb::Body& getScbBodyFast() { return mBody; } // PT: important: keep returning an address here (else update prefetch in SceneQueryManager::addShapes)
|
||
|
|
||
|
PX_FORCE_INLINE Scb::Actor& getScbActorFast() { return mBody; }
|
||
|
PX_FORCE_INLINE const Scb::Actor& getScbActorFast() const { return mBody; }
|
||
|
|
||
|
// Flags
|
||
|
virtual void setRigidBodyFlag(PxRigidBodyFlag::Enum, bool value);
|
||
|
virtual void setRigidBodyFlags(PxRigidBodyFlags inFlags);
|
||
|
PX_FORCE_INLINE PxRigidBodyFlags getRigidBodyFlagsFast() const
|
||
|
{
|
||
|
return getScbBodyFast().getFlags();
|
||
|
}
|
||
|
virtual PxRigidBodyFlags getRigidBodyFlags() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
return getRigidBodyFlagsFast();
|
||
|
}
|
||
|
|
||
|
virtual void setMinCCDAdvanceCoefficient(PxReal advanceCoefficient);
|
||
|
|
||
|
virtual PxReal getMinCCDAdvanceCoefficient() const;
|
||
|
|
||
|
virtual void setMaxDepenetrationVelocity(PxReal maxDepenVel);
|
||
|
|
||
|
virtual PxReal getMaxDepenetrationVelocity() const;
|
||
|
|
||
|
virtual void setMaxContactImpulse(PxReal maxDepenVel);
|
||
|
|
||
|
virtual PxReal getMaxContactImpulse() const;
|
||
|
|
||
|
virtual PxU32 getInternalIslandNodeIndex() const;
|
||
|
|
||
|
protected:
|
||
|
void setCMassLocalPoseInternal(const PxTransform&);
|
||
|
|
||
|
void addSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode);
|
||
|
void clearSpatialForce(PxForceMode::Enum mode, bool force, bool torque);
|
||
|
void setSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode);
|
||
|
|
||
|
PX_INLINE void updateBody2Actor(const PxTransform& newBody2Actor);
|
||
|
|
||
|
PX_FORCE_INLINE void setRigidBodyFlagsInternal(const PxRigidBodyFlags& currentFlags, const PxRigidBodyFlags& newFlags);
|
||
|
|
||
|
#if PX_ENABLE_DEBUG_VISUALIZATION
|
||
|
public:
|
||
|
void visualize(Cm::RenderOutput& out, NpScene* scene);
|
||
|
#endif
|
||
|
|
||
|
PX_FORCE_INLINE bool isKinematic() const
|
||
|
{
|
||
|
return (APIClass::getConcreteType() == PxConcreteType::eRIGID_DYNAMIC) && (getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
Scb::Body mBody;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
NpRigidBodyTemplate<APIClass>::NpRigidBodyTemplate(PxType concreteType, PxBaseFlags baseFlags, PxActorType::Enum type, const PxTransform& bodyPose)
|
||
|
: RigidActorTemplateClass(concreteType, baseFlags)
|
||
|
, mBody(type, bodyPose)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
NpRigidBodyTemplate<APIClass>::~NpRigidBodyTemplate()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
namespace
|
||
|
{
|
||
|
PX_FORCE_INLINE static bool isSimGeom(PxGeometryType::Enum t)
|
||
|
{
|
||
|
return t != PxGeometryType::eTRIANGLEMESH && t != PxGeometryType::ePLANE && t != PxGeometryType::eHEIGHTFIELD;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
bool NpRigidBodyTemplate<APIClass>::attachShape(PxShape& shape)
|
||
|
{
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
PX_CHECK_AND_RETURN_VAL(!(shape.getFlags() & PxShapeFlag::eSIMULATION_SHAPE)
|
||
|
|| isSimGeom(shape.getGeometryType())
|
||
|
|| isKinematic(),
|
||
|
"attachShape: Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are not supported for non-kinematic PxRigidDynamic instances.", false);
|
||
|
return RigidActorTemplateClass::attachShape(shape);
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setCMassLocalPoseInternal(const PxTransform& body2Actor)
|
||
|
{
|
||
|
//the point here is to change the mass distribution w/o changing the actors' pose in the world
|
||
|
|
||
|
PxTransform newBody2World = getGlobalPose() * body2Actor;
|
||
|
|
||
|
mBody.setBody2World(newBody2World, true);
|
||
|
mBody.setBody2Actor(body2Actor);
|
||
|
|
||
|
RigidActorTemplateClass::updateShaderComs();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxTransform NpRigidBodyTemplate<APIClass>::getCMassLocalPose() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return getScbBodyFast().getBody2Actor();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setMass(PxReal mass)
|
||
|
{
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
PX_CHECK_AND_RETURN(PxIsFinite(mass), "PxRigidDynamic::setMass: invalid float");
|
||
|
PX_CHECK_AND_RETURN(mass>=0, "PxRigidDynamic::setMass: mass must be non-negative!");
|
||
|
PX_CHECK_AND_RETURN(this->getType() != PxActorType::eARTICULATION_LINK || mass > 0.0f, "PxRigidDynamic::setMassSpaceInertiaTensor: components must be > 0 for articualtions");
|
||
|
|
||
|
getScbBodyFast().setInverseMass(mass > 0.0f ? 1.0f/mass : 0.0f);
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxReal NpRigidBodyTemplate<APIClass>::getMass() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
const PxReal invMass = mBody.getInverseMass();
|
||
|
|
||
|
return invMass > 0.0f ? 1.0f/invMass : 0.0f;
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxReal NpRigidBodyTemplate<APIClass>::getInvMass() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return mBody.getInverseMass();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setMassSpaceInertiaTensor(const PxVec3& m)
|
||
|
{
|
||
|
PX_CHECK_AND_RETURN(m.isFinite(), "PxRigidDynamic::setMassSpaceInertiaTensor: invalid inertia");
|
||
|
PX_CHECK_AND_RETURN(m.x>=0.0f && m.y>=0.0f && m.z>=0.0f, "PxRigidDynamic::setMassSpaceInertiaTensor: components must be non-negative");
|
||
|
PX_CHECK_AND_RETURN(this->getType() != PxActorType::eARTICULATION_LINK || (m.x > 0.0f && m.y > 0.0f && m.z > 0.0f), "PxRigidDynamic::setMassSpaceInertiaTensor: components must be > 0 for articualtions");
|
||
|
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
mBody.setInverseInertia(invertDiagInertia(m));
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxVec3 NpRigidBodyTemplate<APIClass>::getMassSpaceInertiaTensor() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return invertDiagInertia(mBody.getInverseInertia());
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxVec3 NpRigidBodyTemplate<APIClass>::getMassSpaceInvInertiaTensor() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return mBody.getInverseInertia();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxVec3 NpRigidBodyTemplate<APIClass>::getLinearVelocity() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return mBody.getLinearVelocity();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxVec3 NpRigidBodyTemplate<APIClass>::getAngularVelocity() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
return mBody.getAngularVelocity();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::addSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode)
|
||
|
{
|
||
|
PX_ASSERT(!(mBody.getFlags() & PxRigidBodyFlag::eKINEMATIC));
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case PxForceMode::eFORCE:
|
||
|
{
|
||
|
PxVec3 linAcc, angAcc;
|
||
|
if (force)
|
||
|
{
|
||
|
linAcc = (*force) * mBody.getInverseMass();
|
||
|
force = &linAcc;
|
||
|
}
|
||
|
if (torque)
|
||
|
{
|
||
|
angAcc = mBody.getGlobalInertiaTensorInverse() * (*torque);
|
||
|
torque = &angAcc;
|
||
|
}
|
||
|
mBody.addSpatialAcceleration(force, torque);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eACCELERATION:
|
||
|
mBody.addSpatialAcceleration(force, torque);
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eIMPULSE:
|
||
|
{
|
||
|
PxVec3 linVelDelta, angVelDelta;
|
||
|
if (force)
|
||
|
{
|
||
|
linVelDelta = ((*force) * mBody.getInverseMass());
|
||
|
force = &linVelDelta;
|
||
|
}
|
||
|
if (torque)
|
||
|
{
|
||
|
angVelDelta = (mBody.getGlobalInertiaTensorInverse() * (*torque));
|
||
|
torque = &angVelDelta;
|
||
|
}
|
||
|
mBody.addSpatialVelocity(force, torque);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eVELOCITY_CHANGE:
|
||
|
mBody.addSpatialVelocity(force, torque);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode)
|
||
|
{
|
||
|
PX_ASSERT(!(mBody.getFlags() & PxRigidBodyFlag::eKINEMATIC));
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case PxForceMode::eFORCE:
|
||
|
{
|
||
|
PxVec3 linAcc, angAcc;
|
||
|
if (force)
|
||
|
{
|
||
|
linAcc = (*force) * mBody.getInverseMass();
|
||
|
force = &linAcc;
|
||
|
}
|
||
|
if (torque)
|
||
|
{
|
||
|
angAcc = mBody.getGlobalInertiaTensorInverse() * (*torque);
|
||
|
torque = &angAcc;
|
||
|
}
|
||
|
mBody.setSpatialAcceleration(force, torque);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eACCELERATION:
|
||
|
mBody.setSpatialAcceleration(force, torque);
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eIMPULSE:
|
||
|
{
|
||
|
PxVec3 linVelDelta, angVelDelta;
|
||
|
if (force)
|
||
|
{
|
||
|
linVelDelta = ((*force) * mBody.getInverseMass());
|
||
|
force = &linVelDelta;
|
||
|
}
|
||
|
if (torque)
|
||
|
{
|
||
|
angVelDelta = (mBody.getGlobalInertiaTensorInverse() * (*torque));
|
||
|
torque = &angVelDelta;
|
||
|
}
|
||
|
mBody.addSpatialVelocity(force, torque);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PxForceMode::eVELOCITY_CHANGE:
|
||
|
mBody.addSpatialVelocity(force, torque);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::clearSpatialForce(PxForceMode::Enum mode, bool force, bool torque)
|
||
|
{
|
||
|
PX_ASSERT(!(mBody.getFlags() & PxRigidBodyFlag::eKINEMATIC));
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case PxForceMode::eFORCE:
|
||
|
case PxForceMode::eACCELERATION:
|
||
|
mBody.clearSpatialAcceleration(force, torque);
|
||
|
break;
|
||
|
case PxForceMode::eIMPULSE:
|
||
|
case PxForceMode::eVELOCITY_CHANGE:
|
||
|
mBody.clearSpatialVelocity(force, torque);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#if PX_ENABLE_DEBUG_VISUALIZATION
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::visualize(Cm::RenderOutput& out, NpScene* scene)
|
||
|
{
|
||
|
RigidActorTemplateClass::visualize(out, scene);
|
||
|
|
||
|
if (mBody.getActorFlags() & PxActorFlag::eVISUALIZATION)
|
||
|
{
|
||
|
Scb::Scene& scbScene = scene->getScene();
|
||
|
const PxReal scale = scbScene.getVisualizationParameter(PxVisualizationParameter::eSCALE);
|
||
|
|
||
|
//visualize actor frames
|
||
|
const PxReal actorAxes = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eACTOR_AXES);
|
||
|
if (actorAxes != 0.0f)
|
||
|
out << getGlobalPose() << Cm::DebugBasis(PxVec3(actorAxes));
|
||
|
|
||
|
const PxReal bodyAxes = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_AXES);
|
||
|
if (bodyAxes != 0.0f)
|
||
|
out << mBody.getBody2World() << Cm::DebugBasis(PxVec3(bodyAxes));
|
||
|
|
||
|
const PxReal linVelocity = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_LIN_VELOCITY);
|
||
|
if (linVelocity != 0.0f)
|
||
|
{
|
||
|
out << 0xffffff << PxMat44(PxIdentity) << Cm::DebugArrow(mBody.getBody2World().p,
|
||
|
mBody.getLinearVelocity() * linVelocity, 0.2f * linVelocity);
|
||
|
}
|
||
|
|
||
|
const PxReal angVelocity = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_ANG_VELOCITY);
|
||
|
if (angVelocity != 0.0f)
|
||
|
{
|
||
|
out << 0x000000 << PxMat44(PxIdentity) << Cm::DebugArrow(mBody.getBody2World().p,
|
||
|
mBody.getAngularVelocity() * angVelocity, 0.2f * angVelocity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
PX_FORCE_INLINE void updateDynamicSceneQueryShapes(NpShapeManager& shapeManager, Sq::SceneQueryManager& sqManager, const PxRigidActor& actor)
|
||
|
{
|
||
|
shapeManager.markAllSceneQueryForUpdate(sqManager, actor);
|
||
|
sqManager.get(Sq::PruningIndex::eDYNAMIC).invalidateTimestamp();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
PX_FORCE_INLINE void NpRigidBodyTemplate<APIClass>::setRigidBodyFlagsInternal(const PxRigidBodyFlags& currentFlags, const PxRigidBodyFlags& newFlags)
|
||
|
{
|
||
|
PxRigidBodyFlags filteredNewFlags = newFlags;
|
||
|
//Test to ensure we are not enabling both CCD and kinematic state on a body. This is unsupported
|
||
|
if((filteredNewFlags & PxRigidBodyFlag::eENABLE_CCD) && (filteredNewFlags & PxRigidBodyFlag::eKINEMATIC))
|
||
|
{
|
||
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
|
||
|
"RigidBody::setRigidBodyFlag: kinematic bodies with CCD enabled are not supported! CCD will be ignored.");
|
||
|
filteredNewFlags &= PxRigidBodyFlags(~PxRigidBodyFlag::eENABLE_CCD);
|
||
|
}
|
||
|
|
||
|
if ((filteredNewFlags & PxRigidBodyFlag::eENABLE_CCD) && (filteredNewFlags & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD))
|
||
|
{
|
||
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
|
||
|
"RigidBody::setRigidBodyFlag: eENABLE_CCD can't be raised as the same time as eENABLE_SPECULATIVE_CCD! eENABLE_SPECULATIVE_CCD will be ignored.");
|
||
|
filteredNewFlags &= PxRigidBodyFlags(~PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD);
|
||
|
}
|
||
|
|
||
|
Scb::Body& body = getScbBodyFast();
|
||
|
NpScene* scene = NpActor::getAPIScene(*this);
|
||
|
Sc::Scene* scScene = scene ? &scene->getScene().getScScene() : NULL;
|
||
|
|
||
|
const bool isKinematic = currentFlags & PxRigidBodyFlag::eKINEMATIC;
|
||
|
const bool willBeKinematic = filteredNewFlags & PxRigidBodyFlag::eKINEMATIC;
|
||
|
const bool kinematicSwitchingToDynamic = isKinematic && (!willBeKinematic);
|
||
|
const bool dynamicSwitchingToKinematic = (!isKinematic) && willBeKinematic;
|
||
|
|
||
|
if(kinematicSwitchingToDynamic)
|
||
|
{
|
||
|
NpShapeManager& shapeManager = this->getShapeManager();
|
||
|
PxU32 nbShapes = shapeManager.getNbShapes();
|
||
|
NpShape*const* shapes = shapeManager.getShapes();
|
||
|
bool hasTriangleMesh = false;
|
||
|
for(PxU32 i=0;i<nbShapes;i++)
|
||
|
{
|
||
|
if((shapes[i]->getFlags() & PxShapeFlag::eSIMULATION_SHAPE) && (shapes[i]->getGeometryTypeFast()==PxGeometryType::eTRIANGLEMESH || shapes[i]->getGeometryTypeFast()==PxGeometryType::ePLANE || shapes[i]->getGeometryTypeFast()==PxGeometryType::eHEIGHTFIELD))
|
||
|
{
|
||
|
hasTriangleMesh = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(hasTriangleMesh)
|
||
|
{
|
||
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "RigidBody::setRigidBodyFlag: dynamic meshes/planes/heightfields are not supported!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PxTransform bodyTarget;
|
||
|
if ((currentFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) && body.getKinematicTarget(bodyTarget) && scene)
|
||
|
{
|
||
|
updateDynamicSceneQueryShapes(shapeManager, scene->getSceneQueryManagerFast(), *this);
|
||
|
}
|
||
|
|
||
|
if(scScene)
|
||
|
{
|
||
|
scScene->decreaseNumKinematicsCounter();
|
||
|
scScene->increaseNumDynamicsCounter();
|
||
|
}
|
||
|
|
||
|
body.clearSimStateDataForPendingInsert();
|
||
|
}
|
||
|
else if (dynamicSwitchingToKinematic)
|
||
|
{
|
||
|
if (this->getType() != PxActorType::eARTICULATION_LINK)
|
||
|
{
|
||
|
body.transitionSimStateDataForPendingInsert();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We're an articulation, raise an issue
|
||
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "RigidBody::setRigidBodyFlag: kinematic articulation links are not supported!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(scScene)
|
||
|
{
|
||
|
scScene->decreaseNumDynamicsCounter();
|
||
|
scScene->increaseNumKinematicsCounter();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const bool kinematicSwitchingUseTargetForSceneQuery = isKinematic && willBeKinematic &&
|
||
|
((currentFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) != (filteredNewFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES));
|
||
|
if (kinematicSwitchingUseTargetForSceneQuery)
|
||
|
{
|
||
|
PxTransform bodyTarget;
|
||
|
if (body.getKinematicTarget(bodyTarget) && scene)
|
||
|
{
|
||
|
updateDynamicSceneQueryShapes(this->getShapeManager(), scene->getSceneQueryManagerFast(), *this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
body.setFlags(filteredNewFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setRigidBodyFlag(PxRigidBodyFlag::Enum flag, bool value)
|
||
|
{
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
Scb::Body& body = getScbBodyFast();
|
||
|
const PxRigidBodyFlags currentFlags = body.getFlags();
|
||
|
const PxRigidBodyFlags newFlags = value ? currentFlags | flag : currentFlags & (~PxRigidBodyFlags(flag));
|
||
|
|
||
|
setRigidBodyFlagsInternal(currentFlags, newFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setRigidBodyFlags(PxRigidBodyFlags inFlags)
|
||
|
{
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
|
||
|
Scb::Body& body = getScbBodyFast();
|
||
|
const PxRigidBodyFlags currentFlags = body.getFlags();
|
||
|
|
||
|
setRigidBodyFlagsInternal(currentFlags, inFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setMinCCDAdvanceCoefficient(PxReal minCCDAdvanceCoefficient)
|
||
|
{
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
mBody.setMinCCDAdvanceCoefficient(minCCDAdvanceCoefficient);
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxReal NpRigidBodyTemplate<APIClass>::getMinCCDAdvanceCoefficient() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
return mBody.getMinCCDAdvanceCoefficient();
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setMaxDepenetrationVelocity(PxReal maxDepenVel)
|
||
|
{
|
||
|
PX_CHECK_AND_RETURN(maxDepenVel > 0.0f, "PxRigidDynamic::setMaxDepenetrationVelocity: maxDepenVel must be greater than zero.");
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
mBody.setMaxPenetrationBias(-maxDepenVel);
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxReal NpRigidBodyTemplate<APIClass>::getMaxDepenetrationVelocity() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
return -mBody.getMaxPenetrationBias();
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
void NpRigidBodyTemplate<APIClass>::setMaxContactImpulse(const PxReal maxImpulse)
|
||
|
{
|
||
|
PX_CHECK_AND_RETURN(maxImpulse >= 0.f, "NpRigidBody::setMaxImpulse: impulse limit must be greater than or equal to zero.");
|
||
|
NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
|
||
|
mBody.setMaxContactImpulse(maxImpulse);
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxReal NpRigidBodyTemplate<APIClass>::getMaxContactImpulse() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
return mBody.getMaxContactImpulse();
|
||
|
}
|
||
|
|
||
|
template<class APIClass>
|
||
|
PxU32 NpRigidBodyTemplate<APIClass>::getInternalIslandNodeIndex() const
|
||
|
{
|
||
|
NP_READ_CHECK(NpActor::getOwnerScene(*this));
|
||
|
return mBody.getInternalIslandNodeIndex();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|