// 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. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #include "GuMidphaseInterface.h" #include "GuTetrahedronMesh.h" #include "GuBox.h" using namespace physx; using namespace Gu; void TetrahedronMesh::onRefCountZero() { if (mMeshFactory) { ::onRefCountZero(this, mMeshFactory, false, "PxTetrahedronMesh::release: double deletion detected!"); } } void DeformableVolumeMesh::onRefCountZero() { if (mMeshFactory) { ::onRefCountZero(this, mMeshFactory, false, "PxDeformableVolumeMesh::release: double deletion detected!"); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// DeformableVolumeAuxData::DeformableVolumeAuxData(DeformableVolumeSimulationData& d, DeformableVolumeCollisionData& c, CollisionMeshMappingData& e) : PxDeformableVolumeAuxData(PxType(PxConcreteType::eDEFORMABLE_VOLUME_STATE), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) , mGridModelInvMass(d.mGridModelInvMass) , mGridModelTetraRestPoses(d.mGridModelTetraRestPoses) , mGridModelOrderedTetrahedrons(d.mGridModelOrderedTetrahedrons) , mGMNbPartitions(d.mGridModelNbPartitions) , mGMMaxMaxTetsPerPartitions(d.mGridModelMaxTetsPerPartitions) , mGMRemapOutputSize(d.mGMRemapOutputSize) , mGMRemapOutputCP(d.mGMRemapOutputCP) , mGMAccumulatedPartitionsCP(d.mGMAccumulatedPartitionsCP) , mGMAccumulatedCopiesCP(d.mGMAccumulatedCopiesCP) , mCollisionAccumulatedTetrahedronsRef(e.mCollisionAccumulatedTetrahedronsRef) , mCollisionTetrahedronsReferences(e.mCollisionTetrahedronsReferences) , mCollisionNbTetrahedronsReferences(e.mCollisionNbTetrahedronsReferences) , mCollisionSurfaceVertsHint(e.mCollisionSurfaceVertsHint) , mCollisionSurfaceVertToTetRemap(e.mCollisionSurfaceVertToTetRemap) , mVertsBarycentricInGridModel(e.mVertsBarycentricInGridModel) , mVertsRemapInGridModel(e.mVertsRemapInGridModel) , mTetsRemapColToSim(e.mTetsRemapColToSim) , mTetsRemapSize(e.mTetsRemapSize) , mTetsAccumulatedRemapColToSim(e.mTetsAccumulatedRemapColToSim) , mGMPullIndices(d.mGMPullIndices) , mTetraRestPoses(c.mTetraRestPoses) , mNumTetsPerElement(d.mNumTetsPerElement) { // this constructor takes ownership of memory from the data object d.mGridModelInvMass = 0; d.mGridModelTetraRestPoses = 0; d.mGridModelOrderedTetrahedrons = 0; d.mGMRemapOutputCP = 0; d.mGMAccumulatedPartitionsCP = 0; d.mGMAccumulatedCopiesCP = 0; e.mCollisionAccumulatedTetrahedronsRef = 0; e.mCollisionTetrahedronsReferences = 0; e.mCollisionSurfaceVertsHint = 0; e.mCollisionSurfaceVertToTetRemap = 0; d.mGMPullIndices = 0; e.mVertsBarycentricInGridModel = 0; e.mVertsRemapInGridModel = 0; e.mTetsRemapColToSim = 0; e.mTetsAccumulatedRemapColToSim = 0; c.mTetraRestPoses = 0; } DeformableVolumeAuxData::~DeformableVolumeAuxData() { PX_FREE(mGridModelInvMass); PX_FREE(mGridModelTetraRestPoses); PX_FREE(mGridModelOrderedTetrahedrons); PX_FREE(mGMRemapOutputCP); PX_FREE(mGMAccumulatedPartitionsCP); PX_FREE(mGMAccumulatedCopiesCP); PX_FREE(mCollisionAccumulatedTetrahedronsRef); PX_FREE(mCollisionTetrahedronsReferences); PX_FREE(mCollisionSurfaceVertsHint); PX_FREE(mCollisionSurfaceVertToTetRemap); PX_FREE(mVertsBarycentricInGridModel); PX_FREE(mVertsRemapInGridModel); PX_FREE(mTetsRemapColToSim); PX_FREE(mTetsAccumulatedRemapColToSim); PX_FREE(mGMPullIndices); PX_FREE(mTetraRestPoses); } TetrahedronMesh::TetrahedronMesh(PxU32 nbVertices, PxVec3* vertices, PxU32 nbTetrahedrons, void* tetrahedrons, PxU8 flags, PxBounds3 aabb, PxReal geomEpsilon) : PxTetrahedronMesh(PxType(PxConcreteType::eTETRAHEDRON_MESH), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) , mNbVertices(nbVertices) , mVertices(vertices) , mNbTetrahedrons(nbTetrahedrons) , mTetrahedrons(tetrahedrons) , mFlags(flags) , mMaterialIndices(NULL) , mAABB(aabb) , mGeomEpsilon(geomEpsilon) { } TetrahedronMesh::TetrahedronMesh(TetrahedronMeshData& mesh) : PxTetrahedronMesh(PxType(PxConcreteType::eTETRAHEDRON_MESH), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) , mNbVertices(mesh.mNbVertices) , mVertices(mesh.mVertices) , mNbTetrahedrons(mesh.mNbTetrahedrons) , mTetrahedrons(mesh.mTetrahedrons) , mFlags(mesh.mFlags) , mMaterialIndices(mesh.mMaterialIndices) , mAABB(mesh.mAABB) , mGeomEpsilon(mesh.mGeomEpsilon) { // this constructor takes ownership of memory from the data object mesh.mVertices = 0; mesh.mTetrahedrons = 0; mesh.mMaterialIndices = 0; } TetrahedronMesh::TetrahedronMesh(MeshFactory* meshFactory, TetrahedronMeshData& mesh) : PxTetrahedronMesh(PxType(PxConcreteType::eTETRAHEDRON_MESH), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) , mNbVertices(mesh.mNbVertices) , mVertices(mesh.mVertices) , mNbTetrahedrons(mesh.mNbTetrahedrons) , mTetrahedrons(mesh.mTetrahedrons) , mFlags(mesh.mFlags) , mMaterialIndices(mesh.mMaterialIndices) , mAABB(mesh.mAABB) , mGeomEpsilon(mesh.mGeomEpsilon) , mMeshFactory(meshFactory) { // this constructor takes ownership of memory from the data object mesh.mVertices = 0; mesh.mTetrahedrons = 0; mesh.mMaterialIndices = 0; } TetrahedronMesh::~TetrahedronMesh() { PX_FREE(mTetrahedrons); PX_FREE(mVertices); PX_FREE(mMaterialIndices); } BVTetrahedronMesh::BVTetrahedronMesh(TetrahedronMeshData& mesh, DeformableVolumeCollisionData& d, MeshFactory* factory) : TetrahedronMesh(mesh) , mFaceRemap(d.mFaceRemap) , mGRB_tetraIndices(d.mGRB_primIndices) , mGRB_tetraSurfaceHint(d.mGRB_tetraSurfaceHint) , mGRB_faceRemap(d.mGRB_faceRemap) , mGRB_faceRemapInverse(d.mGRB_faceRemapInverse) , mGRB_BV32Tree(d.mGRB_BV32Tree) { mMeshFactory = factory; bool has16BitIndices = (mesh.mFlags & PxMeshFlag::e16_BIT_INDICES) ? true : false; mMeshInterface4.mVerts = mVertices; // mesh.mVertices; mMeshInterface4.mNbVerts = mesh.mNbVertices; mMeshInterface4.mNbTetrahedrons = mesh.mNbTetrahedrons; mMeshInterface4.mTetrahedrons16 = has16BitIndices ? reinterpret_cast(mTetrahedrons/*mesh.mTetrahedrons*/) : NULL; mMeshInterface4.mTetrahedrons32 = has16BitIndices ? NULL : reinterpret_cast(mTetrahedrons/*mesh.mTetrahedrons*/); mBV4Tree = d.mBV4Tree; mBV4Tree.mMeshInterface = &mMeshInterface4; if (mGRB_BV32Tree) { mMeshInterface32.mVerts = mVertices; // mesh.mVertices; mMeshInterface32.mNbVerts = mesh.mNbVertices; mMeshInterface32.mNbTetrahedrons = mesh.mNbTetrahedrons; mMeshInterface32.mTetrahedrons16 = has16BitIndices ? reinterpret_cast(d.mGRB_primIndices) : NULL; mMeshInterface32.mTetrahedrons32 = has16BitIndices ? NULL : reinterpret_cast(d.mGRB_primIndices); mGRB_BV32Tree->mMeshInterface = &mMeshInterface32; } // this constructor takes ownership of memory from the data object d.mGRB_tetraSurfaceHint = NULL; d.mFaceRemap = NULL; d.mGRB_primIndices = NULL; d.mGRB_faceRemap = NULL; d.mGRB_faceRemapInverse = NULL; d.mGRB_BV32Tree = NULL; mesh.mVertices = NULL; mesh.mTetrahedrons = NULL; } DeformableVolumeMesh::DeformableVolumeMesh(MeshFactory* factory, DeformableVolumeMeshData& d) : PxDeformableVolumeMesh(PxType(PxConcreteType::eDEFORMABLE_VOLUME_MESH), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) , mMeshFactory(factory) { mDeformableVolumeAuxData = PX_NEW(DeformableVolumeAuxData)(d.mSimulationData, d.mCollisionData, d.mMappingData); mCollisionMesh = PX_NEW(BVTetrahedronMesh)(d.mCollisionMesh, d.mCollisionData, factory); mSimulationMesh = PX_NEW(TetrahedronMesh)(factory, d.mSimulationMesh); } DeformableVolumeMesh::~DeformableVolumeMesh() { if (getBaseFlags() & PxBaseFlag::eOWNS_MEMORY) { PX_DELETE(mDeformableVolumeAuxData); PX_DELETE(mCollisionMesh); PX_DELETE(mSimulationMesh); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PT: used to be automatic but making it manual saves bytes in the internal mesh void DeformableVolumeMesh::exportExtraData(PxSerializationContext& stream) { //PX_DEFINE_DYNAMIC_ARRAY(TriangleMesh, mVertices, PxField::eVEC3, mNbVertices, Ps::PxFieldFlag::eSERIALIZE), if (getCollisionMeshFast()->mVertices) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(getCollisionMeshFast()->mVertices, getCollisionMeshFast()->mNbVertices * sizeof(PxVec3)); } /*if (mSurfaceTriangles) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(mSurfaceTriangles, mNbTriangles * 3 * sizeof(PxU32)); }*/ if (getCollisionMeshFast()->mTetrahedrons) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(getCollisionMeshFast()->mTetrahedrons, getCollisionMeshFast()->mNbTetrahedrons * 4 * sizeof(PxU32)); } /*if (mTetSurfaceHint) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(mTetSurfaceHint, mNbTetrahedrons * sizeof(PxU8)); }*/ if (getCollisionMeshFast()->mMaterialIndices) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(getCollisionMeshFast()->mMaterialIndices, getCollisionMeshFast()->mNbTetrahedrons * sizeof(PxU16)); } if (getCollisionMeshFast()->mFaceRemap) { stream.alignData(PX_SERIAL_ALIGN); stream.writeData(getCollisionMeshFast()->mFaceRemap, getCollisionMeshFast()->mNbTetrahedrons * sizeof(PxU32)); } } void DeformableVolumeMesh::importExtraData(PxDeserializationContext& context) { // PT: vertices are followed by indices, so it will be safe to V4Load vertices from a deserialized binary file if (getCollisionMeshFast()->mVertices) getCollisionMeshFast()->mVertices = context.readExtraData(getCollisionMeshFast()->mNbVertices); if (getCollisionMeshFast()->mTetrahedrons) getCollisionMeshFast()->mTetrahedrons = context.readExtraData(4 * getCollisionMeshFast()->mNbTetrahedrons); if (getCollisionMeshFast()->mFaceRemap) getCollisionMeshFast()->mFaceRemap = context.readExtraData(getCollisionMeshFast()->mNbTetrahedrons); getCollisionMeshFast()->mGRB_tetraIndices = NULL; getCollisionMeshFast()->mGRB_tetraSurfaceHint = NULL; getCollisionMeshFast()->mGRB_faceRemap = NULL; getCollisionMeshFast()->mGRB_faceRemapInverse = NULL; getCollisionMeshFast()->mGRB_BV32Tree = NULL; } void DeformableVolumeMesh::release() { Cm::RefCountable_decRefCount(*this); } //PxVec3* TetrahedronMesh::getVerticesForModification() //{ // PxGetFoundation().error(PxErrorCode::eINVALID_OPERATION, PX_FL, "PxDeformableVolumeMesh::getVerticesForModification() is not currently supported."); // // return NULL; //} //PxBounds3 BVTetrahedronMesh::refitBVH() //{ // PxGetFoundation().error(PxErrorCode::eINVALID_OPERATION, PX_FL, "PxDeformableVolumeMesh::refitBVH() is not currently supported."); // // return PxBounds3(mAABB.getMin(), mAABB.getMax()); //}