diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp')
| -rw-r--r-- | PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp | 1342 |
1 files changed, 1342 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp new file mode 100644 index 00000000..45b6beed --- /dev/null +++ b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp @@ -0,0 +1,1342 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxPhysXConfig.h" + +#if PX_USE_CLOTH_API + +#include "NpCloth.h" +#include "NpClothFabric.h" +#include "NpScene.h" +#include "NpPhysics.h" + +using namespace physx; + +// PX_SERIALIZATION +NpCloth::NpCloth(PxBaseFlags baseFlags) : NpClothT(baseFlags), mCloth(PxEmpty), mParticleData(*this) +{ +} +//~PX_SERIALIZATION + +NpCloth::NpCloth(const PxTransform& globalPose, NpClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags) : + NpClothT(PxConcreteType::eCLOTH, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, NULL, NULL), + mCloth(globalPose, fabric.getScClothFabric(), particles, flags), + mClothFabric(&fabric), + mParticleData(*this) +{ + fabric.incRefCount(); +} + +NpCloth::~NpCloth() +{ + // ScClothCore deletion is buffered, but ScClothFabricCore is not + // make sure we don't have a dangling pointer in ScClothCore. + if(1 == mClothFabric->getRefCount()) + mCloth.resetFabric(); + + mClothFabric->decRefCount(); +} + +// PX_SERIALIZATION +void NpCloth::resolveReferences(PxDeserializationContext& context) +{ + context.translatePxBase(mClothFabric); + mClothFabric->incRefCount(); + + // pass fabric down to Scb + mCloth.resolveReferences(mClothFabric->getScClothFabric()); +} + +void NpCloth::requires(PxProcessPxBaseCallback& c) +{ + c.process(*mClothFabric); +} + +NpCloth* NpCloth::createObject(PxU8*& address, PxDeserializationContext& context) +{ + NpCloth* obj = new (address) NpCloth(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(NpCloth); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} +//~PX_SERIALIZATION + +void NpCloth::release() +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, userData); + +// PX_AGGREGATE + // initially no support for aggregates + //NpClothT::release(); // PT: added for PxAggregate +//~PX_AGGREGATE + + NpScene* npScene = NpActor::getAPIScene(*this); + if(npScene) // scene is 0 after scheduling for remove + npScene->removeCloth(*this); + + mCloth.destroy(); +} + + +PxActorType::Enum NpCloth::getType() const +{ + return PxActorType::eCLOTH; +} + + +PxClothFabric* NpCloth::getFabric() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + Sc::ClothFabricCore* scFabric = mCloth.getFabric(); + + size_t scOffset = reinterpret_cast<size_t>(&(reinterpret_cast<NpClothFabric*>(0)->getScClothFabric())); + return reinterpret_cast<NpClothFabric*>(reinterpret_cast<char*>(scFabric)-scOffset); +} + + +void NpCloth::setParticles(const PxClothParticle* currentParticles, const PxClothParticle* previousParticles) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + +#if PX_CHECKED + if (currentParticles) + PX_CHECK_AND_RETURN(checkParticles(mCloth.getNbParticles(), currentParticles), "PxCloth::setParticles: values must be finite and inverse weight must not be negative"); + if (previousParticles) + PX_CHECK_AND_RETURN(checkParticles(mCloth.getNbParticles(), previousParticles), "PxCloth::setParticles: values must be finite and inverse weight must not be negative"); +#endif + + mCloth.setParticles(currentParticles, previousParticles); +} + +PxU32 NpCloth::getNbParticles() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbParticles(); +} + +void NpCloth::setMotionConstraints(const PxClothParticleMotionConstraint* motionConstraints) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkMotionConstraints(mCloth.getNbParticles(), motionConstraints), "PxCloth::setMotionConstraints: values must be finite and radius must not be negative"); +#endif + + mCloth.setMotionConstraints(motionConstraints); + sendPvdMotionConstraints(); +} + + +bool NpCloth::getMotionConstraints(PxClothParticleMotionConstraint* motionConstraintsBuffer) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(motionConstraintsBuffer || !getNbMotionConstraints(), "PxCloth::getMotionConstraints: no motion constraint buffer provided!"); + + return mCloth.getMotionConstraints(motionConstraintsBuffer); +} + +PxU32 NpCloth::getNbMotionConstraints() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbMotionConstraints(); +} + +void NpCloth::setMotionConstraintConfig(const PxClothMotionConstraintConfig& config) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN((config.scale >= 0.0f), "PxCloth::setMotionConstraintConfig: scale must not be negative!"); + + mCloth.setMotionConstraintConfig(config); + sendPvdSimpleProperties(); +} + + +PxClothMotionConstraintConfig NpCloth::getMotionConstraintConfig() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getMotionConstraintConfig(); +} + +void NpCloth::setSeparationConstraints(const PxClothParticleSeparationConstraint* separationConstraints) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkSeparationConstraints(mCloth.getNbParticles(), separationConstraints), "PxCloth::setSeparationConstraints: values must be finite and radius must not be negative"); +#endif + + mCloth.setSeparationConstraints(separationConstraints); + sendPvdSeparationConstraints(); +} + + +bool NpCloth::getSeparationConstraints(PxClothParticleSeparationConstraint* separationConstraintsBuffer) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(separationConstraintsBuffer || !getNbSeparationConstraints(), "PxCloth::getSeparationConstraints: no separation constraint buffer provided!"); + + return mCloth.getSeparationConstraints(separationConstraintsBuffer); +} + +PxU32 NpCloth::getNbSeparationConstraints() const +{ + return mCloth.getNbSeparationConstraints(); +} + +void NpCloth::clearInterpolation() +{ + return mCloth.clearInterpolation(); +} + +void NpCloth::setParticleAccelerations(const PxVec4* particleAccelerations) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkParticleAccelerations(mCloth.getNbParticles(), particleAccelerations), "PxCloth::setParticleAccelerations: values must be finite"); +#endif + + mCloth.setParticleAccelerations(particleAccelerations); + + //TODO: PVD support for particle accelerations + //sendPvdParticleAccelerations(); +} + + +bool NpCloth::getParticleAccelerations(PxVec4* particleAccelerationsBuffer) const +{ + PX_CHECK_MSG(particleAccelerationsBuffer, "PxCloth::getParticleAccelerations: no particle accelerations buffer provided!"); + + return mCloth.getParticleAccelerations(particleAccelerationsBuffer); +} + +PxU32 NpCloth::getNbParticleAccelerations() const +{ + return mCloth.getNbParticleAccelerations(); +} + + +void NpCloth::addCollisionSphere(const PxClothCollisionSphere& sphere) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(mCloth.getNbCollisionSpheres() < 32, "PxCloth::addCollisionSphere: more than 32 spheres is not supported"); + PX_CHECK_AND_RETURN(checkCollisionSpheres(1, &sphere), "PxCloth::addCollisionSphere: position must be finite and radius must not be negative"); + + mCloth.addCollisionSphere(sphere); +} +void NpCloth::removeCollisionSphere(PxU32 index) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.removeCollisionSphere(index); +} +void NpCloth::setCollisionSpheres(const PxClothCollisionSphere* spheresBuffer, PxU32 count) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(count <= 32, "PxCloth::setCollisionSpheres: more than 32 spheres is not supported"); + PX_CHECK_AND_RETURN(checkCollisionSpheres(count, spheresBuffer), "PxCloth::setCollisionSpheres: positions must be finite and radius must not be negative"); +#endif + + mCloth.setCollisionSpheres(spheresBuffer, count); + sendPvdCollisionSpheres(); +} +PxU32 NpCloth::getNbCollisionSpheres() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbCollisionSpheres(); +} + +void NpCloth::getCollisionData(PxClothCollisionSphere* spheresBuffer, PxU32* capsulesBuffer, + PxClothCollisionPlane* planesBuffer, PxU32* convexesBuffer, PxClothCollisionTriangle* trianglesBuffer) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.getCollisionData(spheresBuffer, capsulesBuffer, planesBuffer, convexesBuffer, trianglesBuffer); +} + + +void NpCloth::addCollisionCapsule(PxU32 first, PxU32 second) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(mCloth.getNbCollisionCapsules() < 32, "PxCloth::addCollisionCapsule: more than 32 capsules is not supported"); + + mCloth.addCollisionCapsule(first, second); + + sendPvdCollisionCapsules(); +} +void NpCloth::removeCollisionCapsule(PxU32 index) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.removeCollisionCapsule(index); + + sendPvdCollisionCapsules(); +} +PxU32 NpCloth::getNbCollisionCapsules() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbCollisionCapsules(); +} + +void NpCloth::addCollisionTriangle(const PxClothCollisionTriangle& triangle) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.addCollisionTriangle(triangle); + sendPvdCollisionTriangles(); +} +void NpCloth::removeCollisionTriangle(PxU32 index) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.removeCollisionTriangle(index); + sendPvdCollisionTriangles(); +} +void NpCloth::setCollisionTriangles(const PxClothCollisionTriangle* trianglesBuffer, PxU32 count) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.setCollisionTriangles(trianglesBuffer, count); + sendPvdCollisionTriangles(); +} +PxU32 NpCloth::getNbCollisionTriangles() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbCollisionTriangles(); +} + +void NpCloth::addCollisionPlane(const PxClothCollisionPlane& plane) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(mCloth.getNbCollisionPlanes() < 32, "PxCloth::addCollisionPlane: more than 32 planes is not supported"); + + mCloth.addCollisionPlane(plane); + sendPvdCollisionTriangles(); +} +void NpCloth::removeCollisionPlane(PxU32 index) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.removeCollisionPlane(index); + sendPvdCollisionTriangles(); +} +void NpCloth::setCollisionPlanes(const PxClothCollisionPlane* planesBuffer, PxU32 count) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(count <= 32, "PxCloth::setCollisionPlanes: more than 32 planes is not supported"); + + mCloth.setCollisionPlanes(planesBuffer, count); + sendPvdCollisionTriangles(); +} +PxU32 NpCloth::getNbCollisionPlanes() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbCollisionPlanes(); +} + +void NpCloth::addCollisionConvex(PxU32 mask) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.addCollisionConvex(mask); + sendPvdCollisionTriangles(); +} +void NpCloth::removeCollisionConvex(PxU32 index) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.removeCollisionConvex(index); + sendPvdCollisionTriangles(); +} +PxU32 NpCloth::getNbCollisionConvexes() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbCollisionConvexes(); +} + +void NpCloth::setVirtualParticles(PxU32 numParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(indices, "PxCloth::setVirtualParticles: no triangle vertex and weight index buffer provided!"); + PX_CHECK_MSG(weights, "PxCloth::setVirtualParticles: no triangle vertex weight buffer provided!"); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkVirtualParticles(mCloth.getNbParticles(), numParticles, indices, numWeights, weights), + "PxCloth::setVirtualParticles: out of range value detected"); +#endif + + mCloth.setVirtualParticles(numParticles, indices, numWeights, weights); + sendPvdVirtualParticles(); +} + + +PxU32 NpCloth::getNbVirtualParticles() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbVirtualParticles(); +} + + +void NpCloth::getVirtualParticles(PxU32* indicesBuffer) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(indicesBuffer, "PxCloth::getVirtualParticles: no triangle vertex and weight index buffer provided!"); + + mCloth.getVirtualParticles(indicesBuffer); +} + + +PxU32 NpCloth::getNbVirtualParticleWeights() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getNbVirtualParticleWeights(); +} + + +void NpCloth::getVirtualParticleWeights(PxVec3* weightsBuffer) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(weightsBuffer, "PxCloth::getVirtualParticleWeights: no triangle vertex weight buffer provided!"); + + mCloth.getVirtualParticleWeights(weightsBuffer); +} + + +void NpCloth::setGlobalPose(const PxTransform& pose) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(pose.isSane(), "PxCloth::setGlobalPose: invalid transform!"); + + mCloth.setGlobalPose(pose.getNormalized()); + sendPvdSimpleProperties(); +} + + +PxTransform NpCloth::getGlobalPose() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getGlobalPose(); +} + + +void NpCloth::setTargetPose(const PxTransform& pose) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(pose.isSane(), "PxCloth::setTargetPose: invalid transform!"); + + mCloth.setTargetPose(pose.getNormalized()); + sendPvdSimpleProperties(); +} + + +void NpCloth::setExternalAcceleration(PxVec3 acceleration) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(acceleration.isFinite(), "PxCloth::setExternalAcceleration: invalid values!"); + + mCloth.setExternalAcceleration(acceleration); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getExternalAcceleration() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getExternalAcceleration(); +} + +namespace +{ +#if PX_CHECKED + bool isInRange(const PxVec3 vec, float low, float high) + { + return vec.x >= low && vec.x <= high + && vec.y >= low && vec.y <= high + && vec.z >= low && vec.z <= high; + } +#endif +} + +void NpCloth::setLinearInertiaScale(PxVec3 scale) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setLinearInertiaScale: scale value has to be between 0 and 1!"); + + mCloth.setLinearInertiaScale(scale); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getLinearInertiaScale() const +{ + return mCloth.getLinearInertiaScale(); +} + +void NpCloth::setAngularInertiaScale(PxVec3 scale) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setAngularInertiaScale: scale value has to be between 0 and 1!"); + + mCloth.setAngularInertiaScale(scale); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getAngularInertiaScale() const +{ + return mCloth.getAngularInertiaScale(); +} + +void NpCloth::setCentrifugalInertiaScale(PxVec3 scale) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setCentrifugalInertiaScale: scale value has to be between 0 and 1!"); + + mCloth.setCentrifugalInertiaScale(scale); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getCentrifugalInertiaScale() const +{ + return mCloth.getCentrifugalInertiaScale(); +} + +void NpCloth::setInertiaScale(float scale) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(scale >= 0.0f && scale <= 1.0f, "PxCloth::setInertiaScale: scale value has to be between 0 and 1!"); + + mCloth.setLinearInertiaScale(PxVec3(scale)); + mCloth.setAngularInertiaScale(PxVec3(scale)); + sendPvdSimpleProperties(); +} + +void NpCloth::setDampingCoefficient(PxVec3 dampingCoefficient) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(dampingCoefficient, 0.0f, 1.0f), "PxCloth::setDampingCoefficient: damping coefficient has to be between 0 and 1!"); + + mCloth.setDampingCoefficient(dampingCoefficient); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getDampingCoefficient() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getDampingCoefficient(); +} + + +void NpCloth::setFrictionCoefficient(PxReal frictionCoefficient) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(frictionCoefficient >= 0.0f || frictionCoefficient <= 1.0f, "PxCloth::setFrictionCoefficient: friction coefficient has to be between 0 and 1!"); + + mCloth.setFrictionCoefficient(frictionCoefficient); + sendPvdSimpleProperties(); +} + +PxReal NpCloth::getFrictionCoefficient() const +{ + return mCloth.getFrictionCoefficient(); +} + +void NpCloth::setLinearDragCoefficient(PxVec3 dragCoefficient) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(dragCoefficient, 0.0f, 1.0f), "PxCloth::setLinearDragCoefficient: damping coefficient has to be between 0 and 1!"); + + mCloth.setLinearDragCoefficient(dragCoefficient); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getLinearDragCoefficient() const +{ + return mCloth.getLinearDragCoefficient(); +} + +void NpCloth::setAngularDragCoefficient(PxVec3 dragCoefficient) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(isInRange(dragCoefficient, 0.0f, 1.0f), "PxCloth::setAngularDragCoefficient: damping coefficient has to be between 0 and 1!"); + + mCloth.setAngularDragCoefficient(dragCoefficient); + sendPvdSimpleProperties(); +} + + +PxVec3 NpCloth::getAngularDragCoefficient() const +{ + return mCloth.getAngularDragCoefficient(); +} + +void NpCloth::setDragCoefficient(float coefficient) +{ + setLinearDragCoefficient(PxVec3(coefficient)); + setAngularDragCoefficient(PxVec3(coefficient)); +} + +void NpCloth::setCollisionMassScale(PxReal scalingCoefficient) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(scalingCoefficient >= 0.0f, "PxCloth::setCollisionMassScale: scaling coefficient has to be greater or equal than 0!"); + + mCloth.setCollisionMassScale(scalingCoefficient); +} + + +PxReal NpCloth::getCollisionMassScale() const +{ + return mCloth.getCollisionMassScale(); +} + +void NpCloth::setSelfCollisionDistance(PxReal distance) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(distance >= 0.0f, "PxCloth::setSelfCollisionDistance: distance has to be greater or equal than 0!"); + + mCloth.setSelfCollisionDistance(distance); +} +PxReal NpCloth::getSelfCollisionDistance() const +{ + return mCloth.getSelfCollisionDistance(); +} +void NpCloth::setSelfCollisionStiffness(PxReal stiffness) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(stiffness >= 0.0f, "PxCloth::setSelfCollisionStiffness: stiffness has to be greater or equal than 0!"); + + mCloth.setSelfCollisionStiffness(stiffness); +} +PxReal NpCloth::getSelfCollisionStiffness() const +{ + return mCloth.getSelfCollisionStiffness(); +} + +void NpCloth::setSelfCollisionIndices(const PxU32* indices, PxU32 nbIndices) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.setSelfCollisionIndices(indices, nbIndices); + + sendPvdSelfCollisionIndices(); +} + +bool NpCloth::getSelfCollisionIndices(PxU32* indices) const +{ + return mCloth.getSelfCollisionIndices(indices); +} + +PxU32 NpCloth::getNbSelfCollisionIndices() const +{ + return mCloth.getNbSelfCollisionIndices(); +} + +void NpCloth::setRestPositions(const PxVec4* restPositions) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.setRestPositions(restPositions); + + sendPvdRestPositions(); +} + +bool NpCloth::getRestPositions(PxVec4* restPositions) const +{ + return mCloth.getRestPositions(restPositions); +} + +PxU32 NpCloth::getNbRestPositions() const +{ + return mCloth.getNbRestPositions(); +} + +void NpCloth::setSolverFrequency(PxReal frequency) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(frequency > 0.0f, "PxCloth::setSolverFrequency: solver fequency has to be positive!"); + + mCloth.setSolverFrequency(frequency); + sendPvdSimpleProperties(); +} + + +PxReal NpCloth::getSolverFrequency() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getSolverFrequency(); +} + +void NpCloth::setStiffnessFrequency(PxReal frequency) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(frequency > 0.0f, "PxCloth::setStiffnessFrequency: solver fequency has to be positive!"); + + mCloth.setStiffnessFrequency(frequency); + sendPvdSimpleProperties(); +} + + +PxReal NpCloth::getStiffnessFrequency() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getStiffnessFrequency(); +} + +void NpCloth::setStretchConfig(PxClothFabricPhaseType::Enum type, const PxClothStretchConfig& config) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(config.stiffness >= 0.0f, "PxCloth::setStretchConfig: stiffness must not be negative!"); + PX_CHECK_MSG(config.stiffnessMultiplier >= 0.0f, "PxCloth::setStretchConfig: stiffnessMultiplier must not be negative!"); + PX_CHECK_MSG(config.compressionLimit >= 0.0f, "PxCloth::setStretchConfig: compressionLimit must not be negative!"); + PX_CHECK_MSG(config.compressionLimit <= 1.0f, "PxCloth::setStretchConfig: compressionLimit must not be larger than 1!"); + PX_CHECK_MSG(config.stretchLimit >= 1.0f, "PxCloth::setStretchConfig: stretchLimit must not be smaller than 1!"); + + mCloth.setStretchConfig(type, config); + sendPvdSimpleProperties(); +} + +void NpCloth::setTetherConfig(const PxClothTetherConfig& config) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_MSG(config.stiffness >= 0.0f, "PxCloth::setTetherConfig: stiffness must not be negative!"); + + mCloth.setTetherConfig(config); + sendPvdSimpleProperties(); +} + +PxClothStretchConfig NpCloth::getStretchConfig(PxClothFabricPhaseType::Enum type) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return mCloth.getStretchConfig(type); +} + +PxClothTetherConfig NpCloth::getTetherConfig() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return mCloth.getTetherConfig(); +} + +void NpCloth::setClothFlags(PxClothFlags flags) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.setClothFlags(flags); + sendPvdSimpleProperties(); + + NpScene* scene = NpActor::getAPIScene(*this); + if (scene) + scene->updatePhysXIndicator(); +} + +void NpCloth::setClothFlag(PxClothFlag::Enum flag, bool val) +{ + PxClothFlags flags = mCloth.getClothFlags(); + setClothFlags(val ? flags | flag : flags & ~flag); +} + + +PxClothFlags NpCloth::getClothFlags() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getClothFlags(); +} + +void NpCloth::setWindVelocity(PxVec3 value) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + mCloth.setWindVelocity(value); + sendPvdSimpleProperties(); +} + +PxVec3 NpCloth::getWindVelocity() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getWindVelocity(); +} + +void NpCloth::setWindDrag(PxReal value) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(value >= 0.0f, "PxCloth::setWindDrag: value has to be non-negative!"); + + mCloth.setDragCoefficient(value); + sendPvdSimpleProperties(); +} + +PxReal NpCloth::getWindDrag() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getDragCoefficient(); +} + +void NpCloth::setWindLift(PxReal value) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN(value >= 0.0f, "PxCloth::setWindLift: value has to be non-negative!"); + + mCloth.setLiftCoefficient(value); + sendPvdSimpleProperties(); +} + +PxReal NpCloth::getWindLift() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getLiftCoefficient(); +} + + +bool NpCloth::isSleeping() const +{ + NpScene* scene = NpActor::getOwnerScene(*this); + PX_UNUSED(scene); + + NP_READ_CHECK(scene); + PX_CHECK_AND_RETURN_VAL(scene, "PxCloth::isSleeping: cloth must be in a scene.", true); + + return mCloth.isSleeping(); +} + + +PxReal NpCloth::getSleepLinearVelocity() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getSleepLinearVelocity(); +} + + +void NpCloth::setSleepLinearVelocity(PxReal threshold) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_MSG(threshold >= 0.0f, "PxCloth::setSleepLinearVelocity: threshold must not be negative!"); + + mCloth.setSleepLinearVelocity(threshold); + sendPvdSimpleProperties(); +} + + +void NpCloth::setWakeCounter(PxReal wakeCounterValue) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(PxIsFinite(wakeCounterValue), "PxCloth::setWakeCounter: invalid float."); + PX_CHECK_AND_RETURN(wakeCounterValue>=0.0f, "PxCloth::setWakeCounter: wakeCounterValue must be non-negative!"); + + mCloth.setWakeCounter(wakeCounterValue); +} + + +PxReal NpCloth::getWakeCounter() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getWakeCounter(); +} + + +void NpCloth::wakeUp() +{ + NpScene* scene = NpActor::getOwnerScene(*this); + PX_UNUSED(scene); + + NP_WRITE_CHECK(scene); + PX_CHECK_AND_RETURN(scene, "PxCloth::wakeUp: cloth must be in a scene."); + + mCloth.wakeUp(); +} + + +void NpCloth::putToSleep() +{ + NpScene* scene = NpActor::getOwnerScene(*this); + PX_UNUSED(scene); + + NP_WRITE_CHECK(scene); + PX_CHECK_AND_RETURN(scene, "PxCloth::putToSleep: cloth must be in a scene."); + + mCloth.putToSleep(); +} + + +PxClothParticleData* NpCloth::lockParticleData(PxDataAccessFlags flags) +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + if(!mParticleData.tryLock(flags)) + { + shdfnd::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "PxClothParticleData access through PxCloth::lockParticleData() while its still locked by last call."); + return 0; + } + + mCloth.getParticleData(mParticleData); + return &mParticleData; +} + +PxClothParticleData* NpCloth::lockParticleData() const +{ + return const_cast<NpCloth*>(this)->lockParticleData(PxDataAccessFlag::eREADABLE); +} + +void NpCloth::unlockParticleData() +{ + mCloth.getScCloth().unlockParticleData(); +} + +PxReal NpCloth::getPreviousTimeStep() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + return mCloth.getPreviousTimeStep(); +} + + +PxBounds3 NpCloth::getWorldBounds(float inflation) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + const PxBounds3 bounds = mCloth.getWorldBounds(); + PX_ASSERT(bounds.isValid()); + + // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents. + const PxVec3 center = bounds.getCenter(); + const PxVec3 inflatedExtents = bounds.getExtents() * inflation; + return PxBounds3::centerExtents(center, inflatedExtents); +} + +void NpCloth::setSimulationFilterData(const PxFilterData& data) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + mCloth.setSimulationFilterData(data); +} + +PxFilterData NpCloth::getSimulationFilterData() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return mCloth.getSimulationFilterData(); +} + +void NpCloth::setContactOffset(PxReal offset) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + mCloth.setContactOffset(offset); +} + +PxReal NpCloth::getContactOffset() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return mCloth.getContactOffset(); +} + +void NpCloth::setRestOffset(PxReal offset) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + mCloth.setRestOffset(offset); +} + +PxReal NpCloth::getRestOffset() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return mCloth.getRestOffset(); +} + +#if PX_CHECKED +bool NpCloth::checkParticles(PxU32 numParticles, const PxClothParticle* particles) +{ + for (PxU32 i = 0; i < numParticles; ++i) + { + if(!particles[i].pos.isFinite()) + return false; + if(!PxIsFinite(particles[i].invWeight) || (particles[i].invWeight < 0.0f)) + return false; + } + return true; +} + +bool NpCloth::checkMotionConstraints(PxU32 numConstraints, const PxClothParticleMotionConstraint* constraints) +{ + if(!constraints) + return true; + + for (PxU32 i = 0; i < numConstraints; ++i) + { + if(!constraints[i].pos.isFinite()) + return false; + if(!PxIsFinite(constraints[i].radius) || (constraints[i].radius < 0.0f)) + return false; + } + return true; +} + + +bool NpCloth::checkSeparationConstraints(PxU32 numConstraints, const PxClothParticleSeparationConstraint* constraints) +{ + if(!constraints) + return true; + + for (PxU32 i = 0; i < numConstraints; ++i) + { + if(!constraints[i].pos.isFinite()) + return false; + if(!PxIsFinite(constraints[i].radius) || (constraints[i].radius < 0.0f)) + return false; + } + return true; +} + +bool NpCloth::checkParticleAccelerations(PxU32 numParticles, const PxVec4* accelerations) +{ + if(!accelerations) + return true; + + for (PxU32 i = 0; i < numParticles; ++i) + { + if(!accelerations[i].isFinite()) + return false; + } + return true; +} + +bool NpCloth::checkCollisionSpheres(PxU32 numSpheres, const PxClothCollisionSphere* spheres) +{ + for (PxU32 i = 0; i < numSpheres; ++i) + { + if(!spheres[i].pos.isFinite()) + return false; + if(!PxIsFinite(spheres[i].radius) || (spheres[i].radius < 0.0f)) + return false; + } + return true; +} + +bool NpCloth::checkCollisionSpherePairs(PxU32 numSpheres, PxU32 numPairs, const PxU32* pairIndices) +{ + for (PxU32 i = 0; i < numPairs; ++i) + { + if ((pairIndices[2*i] >= numSpheres) || (pairIndices[2*i + 1] >= numSpheres)) + return false; + } + return true; +} + +bool NpCloth::checkVirtualParticles(PxU32 numParticles, PxU32 numVParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights) +{ + for (PxU32 i = 0; i < numVParticles; ++i) + { + if ((indices[4*i] >= numParticles) || + (indices[4*i + 1] >= numParticles) || + (indices[4*i + 2] >= numParticles) || + (indices[4*i + 3] >= numWeights)) + return false; + } + for (PxU32 i = 0; i < numWeights; ++i) + { + if(!weights[i].isFinite()) + return false; + } + return true; +} +#endif + +#if PX_ENABLE_DEBUG_VISUALIZATION +void NpCloth::visualize(Cm::RenderOutput& out, NpScene* scene) +{ + PxClothParticleData* readData = lockParticleData(); + if (!readData) + return; + + NpClothFabric* fabric = static_cast<NpClothFabric*> (getFabric()); + + PxU32 nbSets = fabric->getNbSets(); + PxU32 nbPhases = fabric->getNbPhases(); + PxU32 nbIndices = fabric->getNbParticleIndices(); + + shdfnd::Array<PxU32> sets(nbSets); + shdfnd::Array<PxClothFabricPhase> phases(nbPhases); + shdfnd::Array<PxU32> indices(nbIndices); + + fabric->getSets(&sets[0], nbSets); + fabric->getPhases(&phases[0], nbPhases); + fabric->getParticleIndices(&indices[0], nbIndices); + + const PxU32 lineColor[] = + { + PxU32(PxDebugColor::eARGB_RED), + PxU32(PxDebugColor::eARGB_GREEN), + PxU32(PxDebugColor::eARGB_BLUE), + PxU32(PxDebugColor::eARGB_YELLOW), + PxU32(PxDebugColor::eARGB_MAGENTA) + }; + + PxU32 colorIndex = 0; + + const PxClothParticle* particles = readData->particles; + const PxTransform xform = getGlobalPose(); + + out << Cm::RenderOutput::LINES; + + for (PxU32 p=0; p < nbPhases; ++p) + { + PxClothFabricPhaseType::Enum phaseType = fabric->getPhaseType(p); + + float scale = 0.0f; + + // check if visualization requested + switch(phaseType) + { + case PxClothFabricPhaseType::eVERTICAL: + scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_VERTICAL); + break; + case PxClothFabricPhaseType::eHORIZONTAL: + scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_HORIZONTAL); + break; + case PxClothFabricPhaseType::eBENDING: + scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_BENDING); + break; + case PxClothFabricPhaseType::eSHEARING: + scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_SHEARING); + break; + case PxClothFabricPhaseType::eINVALID: + case PxClothFabricPhaseType::eCOUNT: + break; + } + + if (scale == 0.0f) + continue; + + out << lineColor[colorIndex]; + + PxU32 set = phases[p].setIndex; + + // draw one set at a time + PxU32 iIt = set ? 2*sets[set-1] : 0; + PxU32 iEnd = 2*sets[set]; + + // iterate over constraints + while (iIt < iEnd) + { + PxU32 i0 = indices[iIt++]; + PxU32 i1 = indices[iIt++]; + + // ideally we would know the mesh normals here and bias off + // the surface slightly but scaling slightly around the center helps + out << xform.transform(particles[i0].pos); + out << xform.transform(particles[i1].pos); + } + + colorIndex = (colorIndex+1)%5; + } + + // draw virtual particles + if (scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_VIRTUAL_PARTICLES) > 0.0f) + { + PxU32 nbVirtualParticles = getNbVirtualParticles(); + + if (nbVirtualParticles) + { + out << Cm::RenderOutput::POINTS; + out << PxU32(PxDebugColor::eARGB_WHITE); + + shdfnd::Array<PxU32> vpIndices(nbVirtualParticles*4); + getVirtualParticles(&vpIndices[0]); + + // get weights table + PxU32 nbVirtualParticleWeights = getNbVirtualParticleWeights(); + shdfnd::Array<PxVec3> vpWeights(nbVirtualParticleWeights); + getVirtualParticleWeights(&vpWeights[0]); + + for (PxU32 i=0; i < nbVirtualParticles; ++i) + { + PxU32 i0 = vpIndices[i*4+0]; + PxU32 i1 = vpIndices[i*4+1]; + PxU32 i2 = vpIndices[i*4+2]; + + PxVec3 v0 = xform.transform(readData->particles[i0].pos); + PxVec3 v1 = xform.transform(readData->particles[i1].pos); + PxVec3 v2 = xform.transform(readData->particles[i2].pos); + + PxVec3 weights = vpWeights[vpIndices[i*4+3]]; + + out << (v0*weights.x + v1*weights.y + v2*weights.z); + } + } + } + + readData->unlock(); +} + +#endif + +#if PX_SUPPORT_PVD +namespace +{ + Vd::ScbScenePvdClient* getScenePvdClient( Scb::Scene* scene ) + { + if(scene ) + { + Vd::ScbScenePvdClient& pvdClient = scene->getScenePvdClient(); + if(pvdClient.checkPvdDebugFlag()) + return &pvdClient; + } + return NULL; + } +} +#endif + +void NpCloth::sendPvdSimpleProperties() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendSimpleProperties( &mCloth ); +#endif +} + +void NpCloth::sendPvdMotionConstraints() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendMotionConstraints( &mCloth ); +#endif +} + +void NpCloth::sendPvdSelfCollisionIndices() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendSelfCollisionIndices( &mCloth ); +#endif +} + +void NpCloth::sendPvdRestPositions() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendRestPositions( &mCloth ); +#endif +} + +void NpCloth::sendPvdSeparationConstraints() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendSeparationConstraints( &mCloth ); +#endif +} + +void NpCloth::sendPvdCollisionSpheres() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendCollisionSpheres( &mCloth ); +#endif +} + +void NpCloth::sendPvdCollisionCapsules() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendCollisionCapsules( &mCloth ); +#endif +} + +void NpCloth::sendPvdCollisionTriangles() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendCollisionTriangles( &mCloth ); +#endif +} + +void NpCloth::sendPvdVirtualParticles() +{ +#if PX_SUPPORT_PVD + Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() ); + if ( pvdClient ) pvdClient->sendVirtualParticles( &mCloth ); +#endif +} + +#endif // PX_USE_CLOTH_API |