385 lines
11 KiB
C++
385 lines
11 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.
|
|
|
|
#include "foundation/PxMathUtils.h"
|
|
#include "foundation/PxQuat.h"
|
|
#include "geometry/PxSphereGeometry.h"
|
|
#include "geometry/PxBoxGeometry.h"
|
|
#include "geometry/PxCapsuleGeometry.h"
|
|
#include "geometry/PxConvexMeshGeometry.h"
|
|
#include "geometry/PxPlaneGeometry.h"
|
|
#include "extensions/PxRigidBodyExt.h"
|
|
#include "extensions/PxSimpleFactory.h"
|
|
#include "PxPhysics.h"
|
|
#include "PxScene.h"
|
|
#include "PxRigidStatic.h"
|
|
#include "PxRigidStatic.h"
|
|
#include "PxRigidDynamic.h"
|
|
#include "PxShape.h"
|
|
|
|
#include "CmPhysXCommon.h"
|
|
#include "PsFoundation.h"
|
|
#include "PsUtilities.h"
|
|
#include "PsInlineArray.h"
|
|
|
|
using namespace physx;
|
|
using namespace shdfnd;
|
|
|
|
namespace
|
|
{
|
|
|
|
bool isDynamicGeometry(PxGeometryType::Enum type)
|
|
{
|
|
return type == PxGeometryType::eBOX
|
|
|| type == PxGeometryType::eSPHERE
|
|
|| type == PxGeometryType::eCAPSULE
|
|
|| type == PxGeometryType::eCONVEXMESH;
|
|
}
|
|
}
|
|
|
|
namespace physx
|
|
{
|
|
PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
PxShape& shape,
|
|
PxReal density)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
|
|
|
|
PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
|
|
if(actor)
|
|
{
|
|
actor->attachShape(shape);
|
|
PxRigidBodyExt::updateMassAndInertia(*actor, density);
|
|
}
|
|
return actor;
|
|
}
|
|
|
|
PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
const PxGeometry& geometry,
|
|
PxMaterial& material,
|
|
PxReal density,
|
|
const PxTransform& shapeOffset)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
|
|
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateDynamic: shapeOffset is not valid.");
|
|
|
|
if(!isDynamicGeometry(geometry.getType()) || density <= 0.0f)
|
|
return NULL;
|
|
|
|
PxShape* shape = sdk.createShape(geometry, material, true);
|
|
if(!shape)
|
|
return NULL;
|
|
|
|
shape->setLocalPose(shapeOffset);
|
|
|
|
PxRigidDynamic* body = shape ? PxCreateDynamic(sdk, transform, *shape, density) : NULL;
|
|
shape->release();
|
|
return body;
|
|
}
|
|
|
|
|
|
|
|
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
PxShape& shape,
|
|
PxReal density)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
|
|
|
|
bool isDynGeom = isDynamicGeometry(shape.getGeometryType());
|
|
if(isDynGeom && density <= 0.0f)
|
|
return NULL;
|
|
|
|
PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
|
|
if(actor)
|
|
{
|
|
actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
|
|
if(!isDynGeom)
|
|
shape.setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
|
|
|
|
actor->attachShape(shape);
|
|
|
|
if(isDynGeom)
|
|
PxRigidBodyExt::updateMassAndInertia(*actor, density);
|
|
else
|
|
{
|
|
actor->setMass(1.f);
|
|
actor->setMassSpaceInertiaTensor(PxVec3(1.f,1.f,1.f));
|
|
}
|
|
}
|
|
|
|
return actor;
|
|
}
|
|
|
|
|
|
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
const PxGeometry& geometry,
|
|
PxMaterial& material,
|
|
PxReal density,
|
|
const PxTransform& shapeOffset)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
|
|
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid.");
|
|
|
|
bool isDynGeom = isDynamicGeometry(geometry.getType());
|
|
if(isDynGeom && density <= 0.0f)
|
|
return NULL;
|
|
|
|
PxShape* shape = sdk.createShape(geometry, material, true);
|
|
if(!shape)
|
|
return NULL;
|
|
|
|
shape->setLocalPose(shapeOffset);
|
|
|
|
PxRigidDynamic* body = PxCreateKinematic(sdk, transform, *shape, density);
|
|
shape->release();
|
|
return body;
|
|
}
|
|
|
|
|
|
|
|
|
|
PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
PxShape& shape)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
|
|
|
|
PxRigidStatic* s = sdk.createRigidStatic(transform);
|
|
if(s)
|
|
s->attachShape(shape);
|
|
return s;
|
|
}
|
|
|
|
PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
|
|
const PxTransform& transform,
|
|
const PxGeometry& geometry,
|
|
PxMaterial& material,
|
|
const PxTransform& shapeOffset)
|
|
{
|
|
|
|
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
|
|
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateStatic: shapeOffset is not valid.");
|
|
|
|
PxShape* shape = sdk.createShape(geometry, material, true);
|
|
if(!shape)
|
|
return NULL;
|
|
|
|
shape->setLocalPose(shapeOffset);
|
|
|
|
PxRigidStatic* s = PxCreateStatic(sdk, transform, *shape);
|
|
shape->release();
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
|
|
PxRigidStatic* PxCreatePlane(PxPhysics& sdk,
|
|
const PxPlane& plane,
|
|
PxMaterial& material)
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(plane.n.isFinite(), "PxCreatePlane: plane normal is not valid.");
|
|
|
|
if (!plane.n.isNormalized())
|
|
return NULL;
|
|
|
|
return PxCreateStatic(sdk, PxTransformFromPlaneEquation(plane), PxPlaneGeometry(), material);
|
|
}
|
|
|
|
|
|
PxShape* PxCloneShape(PxPhysics &physics, const PxShape& from, bool isExclusive)
|
|
{
|
|
Ps::InlineArray<PxMaterial*, 64> materials;
|
|
PxU16 materialCount = from.getNbMaterials();
|
|
materials.resize(materialCount);
|
|
from.getMaterials(materials.begin(), materialCount);
|
|
|
|
PxShape* to = physics.createShape(from.getGeometry().any(), materials.begin(), materialCount, isExclusive, from.getFlags());
|
|
|
|
to->setLocalPose(from.getLocalPose());
|
|
to->setContactOffset(from.getContactOffset());
|
|
to->setRestOffset(from.getRestOffset());
|
|
to->setSimulationFilterData(from.getSimulationFilterData());
|
|
to->setQueryFilterData(from.getQueryFilterData());
|
|
return to;
|
|
}
|
|
|
|
|
|
namespace
|
|
{
|
|
void copyStaticProperties(PxPhysics& physics, PxRigidActor& to, const PxRigidActor& from)
|
|
{
|
|
Ps::InlineArray<PxShape*, 64> shapes;
|
|
shapes.resize(from.getNbShapes());
|
|
|
|
PxU32 shapeCount = from.getNbShapes();
|
|
from.getShapes(shapes.begin(), shapeCount);
|
|
|
|
for(PxU32 i = 0; i < shapeCount; i++)
|
|
{
|
|
PxShape* s = shapes[i];
|
|
if(!s->isExclusive())
|
|
to.attachShape(*s);
|
|
else
|
|
{
|
|
PxShape* newShape = physx::PxCloneShape(physics, *s, true);
|
|
to.attachShape(*newShape);
|
|
newShape->release();
|
|
}
|
|
}
|
|
|
|
to.setActorFlags(from.getActorFlags());
|
|
to.setOwnerClient(from.getOwnerClient());
|
|
to.setDominanceGroup(from.getDominanceGroup());
|
|
}
|
|
}
|
|
|
|
PxRigidStatic* PxCloneStatic(PxPhysics& physicsSDK,
|
|
const PxTransform& transform,
|
|
const PxRigidActor& from)
|
|
{
|
|
PxRigidStatic* to = physicsSDK.createRigidStatic(transform);
|
|
if(!to)
|
|
return NULL;
|
|
|
|
copyStaticProperties(physicsSDK, *to, from);
|
|
|
|
return to;
|
|
}
|
|
|
|
PxRigidDynamic* PxCloneDynamic(PxPhysics& physicsSDK,
|
|
const PxTransform& transform,
|
|
const PxRigidDynamic& from)
|
|
{
|
|
PxRigidDynamic* to = physicsSDK.createRigidDynamic(transform);
|
|
if(!to)
|
|
return NULL;
|
|
|
|
copyStaticProperties(physicsSDK, *to, from);
|
|
|
|
|
|
to->setRigidBodyFlags(from.getRigidBodyFlags());
|
|
|
|
to->setMass(from.getMass());
|
|
to->setMassSpaceInertiaTensor(from.getMassSpaceInertiaTensor());
|
|
to->setCMassLocalPose(from.getCMassLocalPose());
|
|
|
|
to->setLinearVelocity(from.getLinearVelocity());
|
|
to->setAngularVelocity(from.getAngularVelocity());
|
|
|
|
to->setLinearDamping(from.getAngularDamping());
|
|
to->setAngularDamping(from.getAngularDamping());
|
|
|
|
PxU32 posIters, velIters;
|
|
from.getSolverIterationCounts(posIters, velIters);
|
|
to->setSolverIterationCounts(posIters, velIters);
|
|
|
|
to->setMaxAngularVelocity(from.getMaxAngularVelocity());
|
|
to->setMaxDepenetrationVelocity(from.getMaxDepenetrationVelocity());
|
|
to->setSleepThreshold(from.getSleepThreshold());
|
|
to->setStabilizationThreshold(from.getStabilizationThreshold());
|
|
to->setMinCCDAdvanceCoefficient(from.getMinCCDAdvanceCoefficient());
|
|
to->setContactReportThreshold(from.getContactReportThreshold());
|
|
to->setMaxContactImpulse(from.getMaxContactImpulse());
|
|
|
|
return to;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
PxTransform scalePosition(const PxTransform& t, PxReal scale)
|
|
{
|
|
return PxTransform(t.p*scale, t.q);
|
|
}
|
|
}
|
|
|
|
void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps)
|
|
{
|
|
PX_CHECK_AND_RETURN(scale > 0,
|
|
"PxScaleRigidActor requires that the scale parameter is greater than zero");
|
|
|
|
Ps::InlineArray<PxShape*, 64> shapes;
|
|
shapes.resize(actor.getNbShapes());
|
|
actor.getShapes(shapes.begin(), shapes.size());
|
|
|
|
for(PxU32 i=0;i<shapes.size();i++)
|
|
{
|
|
shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale));
|
|
PxGeometryHolder h = shapes[i]->getGeometry();
|
|
|
|
switch(h.getType())
|
|
{
|
|
case PxGeometryType::eSPHERE:
|
|
h.sphere().radius *= scale;
|
|
break;
|
|
case PxGeometryType::ePLANE:
|
|
break;
|
|
case PxGeometryType::eCAPSULE:
|
|
h.capsule().halfHeight *= scale;
|
|
h.capsule().radius *= scale;
|
|
break;
|
|
case PxGeometryType::eBOX:
|
|
h.box().halfExtents *= scale;
|
|
break;
|
|
case PxGeometryType::eCONVEXMESH:
|
|
h.convexMesh().scale.scale *= scale;
|
|
break;
|
|
case PxGeometryType::eTRIANGLEMESH:
|
|
h.triangleMesh().scale.scale *= scale;
|
|
break;
|
|
case PxGeometryType::eHEIGHTFIELD:
|
|
h.heightField().heightScale *= scale;
|
|
h.heightField().rowScale *= scale;
|
|
h.heightField().columnScale *= scale;
|
|
break;
|
|
case PxGeometryType::eINVALID:
|
|
case PxGeometryType::eGEOMETRY_COUNT:
|
|
PX_ASSERT(0);
|
|
}
|
|
shapes[i]->setGeometry(h.any());
|
|
}
|
|
|
|
if(!scaleMassProps)
|
|
return;
|
|
|
|
PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>();
|
|
if(!dynamic)
|
|
return;
|
|
|
|
PxReal scale3 = scale*scale*scale;
|
|
dynamic->setMass(dynamic->getMass()*scale3);
|
|
dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale);
|
|
dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale));
|
|
}
|
|
}
|