// 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-2025 NVIDIA Corporation. All rights reserved. #include "foundation/PxPreprocessor.h" #if PX_SUPPORT_GPU_PHYSX #include "ScDeformableVolumeSim.h" #include "geometry/PxTetrahedronMesh.h" using namespace physx; using namespace Dy; Sc::DeformableVolumeSim::DeformableVolumeSim(DeformableVolumeCore& core, Scene& scene) : GPUActorSim(scene, core, NULL) { mLLDeformableVolume = scene.createLLDeformableVolume(this); mNodeIndex = scene.getSimpleIslandManager()->addNode(false, false, IG::Node::eDEFORMABLE_VOLUME_TYPE, mLLDeformableVolume); scene.getSimpleIslandManager()->activateNode(mNodeIndex); mLLDeformableVolume->setElementId(mShapeSim.getElementID()); } Sc::DeformableVolumeSim::~DeformableVolumeSim() { if (!mLLDeformableVolume) return; mScene.destroyLLDeformableVolume(*mLLDeformableVolume); mScene.getSimpleIslandManager()->removeNode(mNodeIndex); mCore.setSim(NULL); } bool Sc::DeformableVolumeSim::isSleeping() const { IG::IslandSim& sim = mScene.getSimpleIslandManager()->getAccurateIslandSim(); return sim.getActiveNodeIndex(mNodeIndex) == PX_INVALID_NODE; } void Sc::DeformableVolumeSim::onSetWakeCounter() { mScene.getSimulationController()->setSoftBodyWakeCounter(mLLDeformableVolume); if (mLLDeformableVolume->getCore().wakeCounter > 0.f) mScene.getSimpleIslandManager()->activateNode(mNodeIndex); else mScene.getSimpleIslandManager()->deactivateNode(mNodeIndex); } void Sc::DeformableVolumeSim::attachShapeCore(ShapeCore* core) { mShapeSim.setCore(core); { PX_ASSERT(getWorldBounds().isFinite()); const PxU32 index = mShapeSim.getElementID(); mScene.getBoundsArray().setBounds(getWorldBounds(), index); addToAABBMgr(Bp::FilterType::DEFORMABLE_VOLUME); } PxsShapeCore* shapeCore = const_cast(&core->getCore()); mLLDeformableVolume->setShapeCore(shapeCore); } PxBounds3 Sc::DeformableVolumeSim::getWorldBounds() const { const PxTetrahedronMeshGeometry& tetGeom = static_cast(mShapeSim.getCore().getGeometry()); return tetGeom.tetrahedronMesh->getLocalBounds(); } void Sc::DeformableVolumeSim::attachSimulationMesh(PxTetrahedronMesh* simulationMesh, PxDeformableVolumeAuxData* simulationState) { mLLDeformableVolume->setSimShapeCore(simulationMesh, simulationState); } PxTetrahedronMesh* Sc::DeformableVolumeSim::getSimulationMesh() { return mLLDeformableVolume->getSimulationMesh(); } PxDeformableVolumeAuxData* Sc::DeformableVolumeSim::getAuxData() { return mLLDeformableVolume->getAuxData(); } PxTetrahedronMesh* Sc::DeformableVolumeSim::getCollisionMesh() { return mLLDeformableVolume->getCollisionMesh(); } void Sc::DeformableVolumeSim::enableSelfCollision() { if (isActive()) { mScene.getSimulationController()->activateSoftbodySelfCollision(mLLDeformableVolume); } } void Sc::DeformableVolumeSim::disableSelfCollision() { if (isActive()) { mScene.getSimulationController()->deactivateSoftbodySelfCollision(mLLDeformableVolume); } } /*void Sc::DeformableVolumeSim::activate() { // Activate body //{ // PX_ASSERT((!isKinematic()) || notInScene() || readInternalFlag(InternalFlags(BF_KINEMATIC_MOVED | BF_KINEMATIC_SURFACE_VELOCITY))); // kinematics should only get activated when a target is set. // // exception: object gets newly added, then the state change will happen later // if (!isArticulationLink()) // { // mLLBody.mInternalFlags &= (~PxsRigidBody::eFROZEN); // // Put in list of activated bodies. The list gets cleared at the end of a sim step after the sleep callbacks have been fired. // getScene().onBodyWakeUp(this); // } // BodyCore& core = getBodyCore(); // if (core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW) // { // PX_ASSERT(!getScene().isInPosePreviewList(*this)); // getScene().addToPosePreviewList(*this); // } // createSqBounds(); //} activateInteractions(*this); } void Sc::DeformableVolumeSim::deactivate() { deactivateInteractions(*this); // Deactivate body //{ // PX_ASSERT((!isKinematic()) || notInScene() || !readInternalFlag(BF_KINEMATIC_MOVED)); // kinematics should only get deactivated when no target is set. // // exception: object gets newly added, then the state change will happen later // BodyCore& core = getBodyCore(); // if (!readInternalFlag(BF_ON_DEATHROW)) // { // // Set velocity to 0. // // Note: this is also fine if the method gets called because the user puts something to sleep (this behavior is documented in the API) // PX_ASSERT(core.getWakeCounter() == 0.0f); // const PxVec3 zero(0.0f); // core.setLinearVelocityInternal(zero); // core.setAngularVelocityInternal(zero); // setForcesToDefaults(!(mLLBody.mInternalFlags & PxsRigidBody::eDISABLE_GRAVITY)); // } // if (!isArticulationLink()) // Articulations have their own sleep logic. // getScene().onBodySleep(this); // if (core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW) // { // PX_ASSERT(getScene().isInPosePreviewList(*this)); // getScene().removeFromPosePreviewList(*this); // } // destroySqBounds(); //} }*/ PxU32 Sc::DeformableVolumeSim::getGpuIndex() const { return mLLDeformableVolume->getGpuIndex(); } #endif //PX_SUPPORT_GPU_PHYSX