NVIDIA-Omniverse / PhysX

NVIDIA PhysX SDK
BSD 3-Clause "New" or "Revised" License
2.56k stars 365 forks source link

Assert in PxcBruteForceOverlapBackface #302

Open korokuchum opened 2 months ago

korokuchum commented 2 months ago

Library and Version

PhysX v5.4.0

Operating System

Windows 11

Steps to Trigger Behavior

Couldn't find any specific steps. Here's how I got this issue: 1) Create aggregate and add a bunch of Rigid Bodies each with single small convex shape (RigidBodies can overlap) 2) Add aggregate to world 3) Wait for a moment and upon one of the collisions you will receive assert.

Scene setup

Broad Phase Type: Any Solver Type: Any Friction Type: Any

Expected Behavior

Simulation runs without asserts

Actual Behavior

Assert during simulation

Call stack

PhysXFoundation_64.dll!physx::PxAssert(const char * expr, const char * file, int line, bool & ignore) Line 59   C++ Symbols loaded.
PhysXCommon_64.dll!PxcBruteForceOverlapBackface(const physx::PxBounds3 & hullBounds0, const physx::PxBounds3 & hullBounds1, const physx::Gu::PolygonalData & polyData0, const physx::Gu::PolygonalData & polyData1, const physx::PxMat34T<float> & world0, const physx::PxMat34T<float> & world1, const physx::Cm::FastVertex2ShapeScaling & scaling0, const physx::Cm::FastVertex2ShapeScaling & scaling1, const physx::PxMat34T<float> & m0to1, const physx::PxMat34T<float> & m1to0, const physx::PxVec3T<float> & delta, unsigned int & id0, unsigned int & id1, float & depth, physx::PxVec3T<float> & sep, physx::Gu::PxcSepAxisType & code, float contactDistance, float toleranceLength) Line 596   C++ Symbols loaded.
PhysXCommon_64.dll!GuContactHullHull(const physx::Gu::PolygonalData & polyData0, const physx::Gu::PolygonalData & polyData1, const physx::PxBounds3 & hullBounds0, const physx::PxBounds3 & hullBounds1, const physx::PxTransformT<float> & transform0, const physx::PxTransformT<float> & transform1, const physx::Gu::NarrowPhaseParams & params, physx::PxContactBuffer & contactBuffer, const physx::Cm::FastVertex2ShapeScaling & scaling0, const physx::Cm::FastVertex2ShapeScaling & scaling1, bool idtScale0, bool idtScale1) Line 870  C++ Symbols loaded.
PhysXCommon_64.dll!physx::Gu::contactConvexConvex(const physx::PxGeometry & shape0, const physx::PxGeometry & shape1, const physx::PxTransformPadded & transform0, const physx::PxTransformPadded & transform1, const physx::Gu::NarrowPhaseParams & params, physx::Gu::Cache & cache, physx::PxContactBuffer & contactBuffer, physx::PxRenderOutput * renderOutput) Line 803   C++ Symbols loaded.
PhysX_64.dll!PxcContactConvexConvex(const physx::PxGeometry & shape0, const physx::PxGeometry & shape1, const physx::PxTransformPadded & transform0, const physx::PxTransformPadded & transform1, const physx::Gu::NarrowPhaseParams & params, physx::Gu::Cache & cache, physx::PxContactBuffer & contactBuffer, physx::PxRenderOutput * renderOutput) Line 58  C++ Symbols loaded.
PhysX_64.dll!physx::PxcCacheLocalContacts(physx::PxcNpThreadContext & context, physx::Gu::Cache & pairContactCache, const physx::PxTransformPadded & tm0, const physx::PxTransformPadded & tm1, bool(*)(const physx::PxGeometry &, const physx::PxGeometry &, const physx::PxTransformPadded &, const physx::PxTransformPadded &, const physx::Gu::NarrowPhaseParams &, physx::Gu::Cache &, physx::PxContactBuffer &, physx::PxRenderOutput *) conMethod, const physx::PxGeometry & shape0, const physx::PxGeometry & shape1) Line 407  C++ Symbols loaded.
PhysX_64.dll!discreteNarrowPhase<1>(physx::PxcNpThreadContext & context, const physx::PxcNpWorkUnit & input, physx::Gu::Cache & cache, physx::PxsContactManagerOutput & output, unsigned __int64 contextID) Line 438    C++ Symbols loaded.
PhysX_64.dll!physx::PxcDiscreteNarrowPhase(physx::PxcNpThreadContext & context, const physx::PxcNpWorkUnit & input, physx::Gu::Cache & cache, physx::PxsContactManagerOutput & output, unsigned __int64 contextID) Line 507 C++ Symbols loaded.
PhysX_64.dll!PxsCMDiscreteUpdateTask::processCms<&physx::PxcDiscreteNarrowPhase>(physx::PxcNpThreadContext * threadContext) Line 446    C++ Symbols loaded.
PhysX_64.dll!PxsCMDiscreteUpdateTask::runInternal() Line 514    C++ Symbols loaded.
PhysX_64.dll!physx::Cm::Task::run() Line 66 C++ Symbols loaded.
vreutskyy commented 2 months ago

Hi @korokuchum. Thanks for the report.

PierreTerdiman commented 2 months ago

This assert means that some precomputed values are incorrect for some of the convexes, potentially leading to missed collisions. There isn't much we can do without either a repro, or at least the vertices used in that example (so that we can cook the convex on our side and check what happens). This would be unrelated to aggregates.

On the other hand, this is the "legacy" contact generation codepath which was known to have defects for convex-vs-convex collisions anyway. So even if we fix that assert, this specific codepath is ultimately unreliable - and it was the main reason for the introduction of the PCM codepath.

I would therefore suggest switching to PCM (PxSceneFlag::eENABLE_PCM) here.

korokuchum commented 2 months ago

With PCM enabled I have different assert.

Call Stack

PhysXFoundation_64.dll!physx::PxAssert(const char * expr, const char * file, int line, bool & ignore) Line 59   C++ Symbols loaded.
PhysXCommon_64.dll!testEdgeNormal(const physx::Gu::PolygonalData & polyData0, const physx::Gu::PolygonalData & polyData1, const physx::Gu::SupportLocal * map0, const physx::Gu::SupportLocal * map1, const physx::aos::PxMatTransformV & transform0To1, const physx::aos::PxMatTransformV & transform1To0, const __m128 & contactDist, __m128 & minOverlap, __m128 & edgeNormalIn0, physx::Gu::FeatureStatus edgeStatus, physx::Gu::FeatureStatus & status) Line 314   C++ Symbols loaded.
PhysXCommon_64.dll!physx::Gu::generateFullContactManifold(const physx::Gu::PolygonalData & polyData0, const physx::Gu::PolygonalData & polyData1, const physx::Gu::SupportLocal * map0, const physx::Gu::SupportLocal * map1, physx::Gu::PersistentContact * manifoldContacts, unsigned int & numContacts, const __m128 & contactDist, const __m128 & normal, const __m128 & closestA, const __m128 & closestB, float marginA, float marginB, bool doOverlapTest, physx::PxRenderOutput * renderOutput, float toleranceLength) Line 561 C++ Symbols loaded.
PhysXCommon_64.dll!fullContactsGenerationConvexConvex(const physx::Gu::GjkConvex * relativeConvex, const physx::Gu::GjkConvex * localConvex, const physx::aos::PxTransformV & transf0, const physx::aos::PxTransformV & transf1, bool idtScale0, bool idtScale1, physx::Gu::PersistentContact * manifoldContacts, physx::PxContactBuffer & contactBuffer, physx::Gu::PersistentContactManifold & manifold, __m128 & normal, const __m128 & closestA, const __m128 & closestB, const __m128 & contactDist, bool doOverlapTest, physx::PxRenderOutput * renderOutput, float toleranceLength) Line 64  C++ Symbols loaded.
PhysXCommon_64.dll!generateOrProcessContactsConvexConvex(const physx::Gu::GjkConvex * relativeConvex, const physx::Gu::GjkConvex * localConvex, const physx::aos::PxTransformV & transf0, const physx::aos::PxTransformV & transf1, const physx::aos::PxMatTransformV & aToB, physx::Gu::GjkStatus status, physx::Gu::GjkOutput & output, physx::Gu::PersistentContactManifold & manifold, physx::PxContactBuffer & contactBuffer, unsigned int initialContacts, const __m128 minMargin, const __m128 contactDist, bool idtScale0, bool idtScale1, float toleranceLength, physx::PxRenderOutput * renderOutput) Line 128    C++ Symbols loaded.
PhysXCommon_64.dll!convexHullNoScale0(const physx::Gu::ConvexHullV & convexHull0, const physx::Gu::ConvexHullV & convexHull1, const physx::aos::PxTransformV & transf0, const physx::aos::PxTransformV & transf1, const physx::aos::PxMatTransformV & aToB, physx::Gu::GjkOutput & output, physx::Gu::PersistentContactManifold & manifold, physx::PxContactBuffer & contactBuffer, unsigned int initialContacts, const __m128 minMargin, const __m128 contactDist, bool idtScale1, float toleranceLength, physx::PxRenderOutput * renderOutput) Line 154   C++ Symbols loaded.
PhysXCommon_64.dll!physx::Gu::pcmContactConvexConvex(const physx::PxGeometry & shape0, const physx::PxGeometry & shape1, const physx::PxTransformPadded & transform0, const physx::PxTransformPadded & transform1, const physx::Gu::NarrowPhaseParams & params, physx::Gu::Cache & cache, physx::PxContactBuffer & contactBuffer, physx::PxRenderOutput * renderOutput) Line 256    C++ Symbols loaded.
PhysX_64.dll!PxcPCMContactConvexConvex(const physx::PxGeometry & shape0, const physx::PxGeometry & shape1, const physx::PxTransformPadded & transform0, const physx::PxTransformPadded & transform1, const physx::Gu::NarrowPhaseParams & params, physx::Gu::Cache & cache, physx::PxContactBuffer & contactBuffer, physx::PxRenderOutput * renderOutput) Line 82   C++ Symbols loaded.
PhysX_64.dll!discreteNarrowPhase<0>(physx::PxcNpThreadContext & context, const physx::PxcNpWorkUnit & input, physx::Gu::Cache & cache, physx::PxsContactManagerOutput & output, unsigned __int64 contextID) Line 462    C++ Symbols loaded.
PhysX_64.dll!physx::PxcDiscreteNarrowPhasePCM(physx::PxcNpThreadContext & context, const physx::PxcNpWorkUnit & input, physx::Gu::Cache & cache, physx::PxsContactManagerOutput & output, unsigned __int64 contextID) Line 513  C++ Symbols loaded.
PhysX_64.dll!PxsCMDiscreteUpdateTask::processCms<&physx::PxcDiscreteNarrowPhasePCM>(physx::PxcNpThreadContext * threadContext) Line 446 C++ Symbols loaded.
PhysX_64.dll!PxsCMDiscreteUpdateTask::runInternal() Line 510    C++ Symbols loaded.
PhysX_64.dll!physx::Cm::Task::run() Line 66 C++ Symbols loaded.
korokuchum commented 2 months ago

Here's the problematic mesh: https://drive.google.com/file/d/1CEb4LRIzhDEll5m37AKbLvewLbEML3Lb/view?usp=sharing In this case convex meshes are created from submeshes in attached mesh.

Mesh description flags: physx::PxConvexFlag::eCOMPUTE_CONVEX | physx::PxConvexFlag::eSHIFT_VERTICES

Cooking parameters:

  | Name | Value | Type -- | -- | -- | --   | areaTestEpsilon | 0.00999999978 | float   | planeTolerance | 0.000699999975 | float   | convexMeshCookingType | eQUICKHULL (0) | physx::PxConvexMeshCookingType::Enum   | suppressTriangleMeshRemapTable | false | bool   | buildTriangleAdjacencies | false | bool   | buildGPUData | false | bool ◢ | scale | {length=1.00000000 speed=10.0000000 } | physx::PxTolerancesScale   | length | 1.00000000 | float   | speed | 10.0000000 | float ◢ | meshPreprocessParams | {mBits=0 } | physx::PxFlags   | mBits | 0 | unsigned int   | meshWeldTolerance | 0.00000000 | float   | meshAreaMinLimit | 0.00000000 | float   | meshEdgeLengthMaxLimit | 500.000000 | float ◢ | midphaseDesc | {mBVH33Desc={meshSizePerformanceTradeOff=5.605e-45#DEN meshCookingHint=2 } mBVH34Desc={numPrimsPerLeaf=...} ...} | physx::PxMidphaseDesc   | ▶ mBVH33Desc | {meshSizePerformanceTradeOff=5.605e-45#DEN meshCookingHint=2 } | physx::PxBVH33MidphaseDesc   | ◢ mBVH34Desc | {numPrimsPerLeaf=4 buildStrategy=eSAH (2) quantized=true } | physx::PxBVH34MidphaseDesc   | numPrimsPerLeaf | 4 | unsigned int   | buildStrategy | eSAH (2) | physx::PxBVH34BuildStrategy::Enum   | quantized | true | bool   | mType | eBVH34 (1) | physx::PxMeshMidPhase::Enum   | gaussMapLimit | 32 | unsigned int   | maxWeightRatioInTet | 3.40282347e+38 | float