Giter Club home page Giter Club logo

Comments (5)

preist-nvidia avatar preist-nvidia commented on July 17, 2024

Thank you for the report! We'll have a look. Internal tracking: PX-4672

from physx.

adenzler-nvidia avatar adenzler-nvidia commented on July 17, 2024

Thanks for the report! I'm trying to reproduce this but my first attempts are failing, but I'm on windows right now. Will try linux later. Could you maybe give me a hint about the order of magnitude of the number of shapes? Did you have additional actors in the scene, and if so, what kind? Are you using GPU dynamics?

from physx.

PhilNad avatar PhilNad commented on July 17, 2024

Hi @adenzler-nvidia,

I could finally trigger the crash 100% of the time with the following code. I believe that it might be related to the behaviour noticed by @Elercia in #226.

The code creates three kinematic actors, to which a great number of boxes and spheres are exclusively attached to. Actors 2 and 3 are completely overlapping, and actor 1 is partly overlapping with the others. The number of shapes attached to each object is set to 2*N^3. When N = 14, the crash is triggered when calling PX_RELEASE(), at which point 26940 + 0 + 26940 contact pairs were detected. When N = 13, 18456 + 57244 + 18456 contact pairs are detected but the crash is not triggered.

Note that the contact pairs between the actors that are entirely overlapping are not being detected when N = 14 but are detected when N = 13.

I hope this helps.

#include <iostream>
#include <vector>
#include "PxPhysicsAPI.h"
#include "eigen3/Eigen/Eigen"

using namespace physx;
using namespace std;
using namespace Eigen;

static PxDefaultAllocator		gAllocator;
static PxDefaultErrorCallback	gErrorCallback;
static PxFoundation*			gFoundation = NULL;
static PxPhysics*				gPhysics;
static PxDefaultCpuDispatcher*	gDispatcher;
static PxScene*					gScene;
static PxMaterial*				gMaterial;

static PxFilterFlags contactReportFilterShader(	PxFilterObjectAttributes attributes0, PxFilterData filterData0, 
												PxFilterObjectAttributes attributes1, PxFilterData filterData1,
												PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
	PX_UNUSED(attributes0);
	PX_UNUSED(attributes1);
	PX_UNUSED(filterData0);
	PX_UNUSED(filterData1);
	PX_UNUSED(constantBlockSize);
	PX_UNUSED(constantBlock);

	pairFlags = PxPairFlag::eDETECT_DISCRETE_CONTACT
                | PxPairFlag::eNOTIFY_TOUCH_FOUND
			    | PxPairFlag::eNOTIFY_CONTACT_POINTS;

	return PxFilterFlag::eDEFAULT;
}

class ContactReportCallback: public PxSimulationEventCallback
{
	void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count)	{ PX_UNUSED(constraints); PX_UNUSED(count); }
	void onWake(PxActor** actors, PxU32 count)							{ PX_UNUSED(actors); PX_UNUSED(count); }
	void onSleep(PxActor** actors, PxU32 count)							{ PX_UNUSED(actors); PX_UNUSED(count); }
	void onTrigger(PxTriggerPair* pairs, PxU32 count)					{ PX_UNUSED(pairs); PX_UNUSED(count); }
	void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
	void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs) 
	{
		PX_UNUSED((pairHeader));
        cout << "Contact detected: " << nbPairs << " pairs" << endl;
    }
};
ContactReportCallback gContactReportCallback;


int main()
{
    gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);

    gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale());

    PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
    sceneDesc.gravity = PxVec3(0.0f, 0.0f, -9.81f);
    gDispatcher = PxDefaultCpuDispatcherCreate(2);
    sceneDesc.cpuDispatcher	= gDispatcher;

    sceneDesc.kineKineFilteringMode   = PxPairFilteringMode::eKEEP;
    sceneDesc.filterShader	          = contactReportFilterShader;
    sceneDesc.simulationEventCallback = &gContactReportCallback;

    gScene = gPhysics->createScene(sceneDesc);
    gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.1f);

    //Spheres positions - create a grid of NxNxN spheres
    vector<Vector3f> sphere_positions;
    //NOTE: The crash is triggered when N >= 14 only.
    // With N=13, there are 18456 + 57244 + 18456 contact pairs detected.
    // With N=14, there are 26940 + 0 + 26940 contact pairs detected.
    int N = 14;
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            for(int k = 0; k < N; k++){
                sphere_positions.push_back(Vector3f(i*0.1, j*0.1, k*0.1));
            }
        }
    }

    /// OBJECT 1

    PxArray<PxShape*> shapes;
    for(int i = 0; i < sphere_positions.size(); i++)
    {
        //Create a sphere
        PxSphereGeometry sphereGeometry = PxSphereGeometry(0.01);
        PxShape* sphere = gPhysics->createShape(sphereGeometry, *gMaterial, true);

        //Create a box
        PxBoxGeometry boxGeometry = PxBoxGeometry(0.05, 0.05, 0.05);
        PxShape* box = gPhysics->createShape(boxGeometry, *gMaterial, true);

        //Set the position
        Vector3f pos = sphere_positions[i];
        
        sphere->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        sphere->setRestOffset(0);
        sphere->setContactOffset(1e-6);

        box->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        box->setRestOffset(0);
        box->setContactOffset(1e-6);

        shapes.pushBack(sphere);
        shapes.pushBack(box);
    }

    //Pose of the actor/object in the world frame column by column [col0 | col1 | col2 | col3]
    Matrix4f pose;
    pose << 1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1;
    PxTransform pxPose = PxTransform(PxMat44(
        PxVec3(pose(0,0), pose(1,0), pose(2,0)),
        PxVec3(pose(0,1), pose(1,1), pose(2,1)),
        PxVec3(pose(0,2), pose(1,2), pose(2,2)),
        PxVec3(pose(0,3), pose(1,3), pose(2,3))));

    //Create a kinematic actor and attach all spheres to it
    PxRigidDynamic* actor = gPhysics->createRigidDynamic(pxPose);
    actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);

    //Attach all shapes in the object to the actor
    for(int i = 0; i < shapes.size(); i++){
        if(shapes[i] != nullptr){
            actor->attachShape(*shapes[i]);
            //We release the shape after it has been attached such that when the actor
            // is released, the shape is also released.
            shapes[i]->release();
        }
    }

    actor->setMass(1);
    actor->setCMassLocalPose(PxTransform(PxVec3(0,0,0)));
    gScene->addActor(*actor);
    actor->setGlobalPose(pxPose);
    actor->setKinematicTarget(pxPose);

    //Run simulation
    float dt = 1/1000.0;
    gScene->simulate(dt/2);
    gScene->fetchResults(true);
    gScene->simulate(dt/2);
    gScene->fetchResults(true);

    /// OBJECT 2 with overlapping spheres

    PxArray<PxShape*> shapes2;
    for(int i = 0; i < sphere_positions.size(); i++)
    {
        //Create a sphere
        PxSphereGeometry sphereGeometry = PxSphereGeometry(0.01);
        PxShape* sphere = gPhysics->createShape(sphereGeometry, *gMaterial, true);

        //Create a box
        PxBoxGeometry boxGeometry = PxBoxGeometry(0.05, 0.05, 0.05);
        PxShape* box = gPhysics->createShape(boxGeometry, *gMaterial, true);

        //Set the position
        Vector3f pos = sphere_positions[i];
        
        sphere->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        sphere->setRestOffset(0);
        sphere->setContactOffset(1e-6);

        box->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        box->setRestOffset(0);
        box->setContactOffset(1e-6);

        shapes2.pushBack(sphere);
        shapes2.pushBack(box);
    }

    pose << 1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0.9,
            0, 0, 0, 1;
    pxPose = PxTransform(PxMat44(
        PxVec3(pose(0,0), pose(1,0), pose(2,0)),
        PxVec3(pose(0,1), pose(1,1), pose(2,1)),
        PxVec3(pose(0,2), pose(1,2), pose(2,2)),
        PxVec3(pose(0,3), pose(1,3), pose(2,3))));

    //Create a kinematic actor and attach all spheres to it
    PxRigidDynamic* actor2 = gPhysics->createRigidDynamic(pxPose);
    actor2->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);

    //Attach all shapes in the object to the actor
    for(int i = 0; i < shapes2.size(); i++){
        if(shapes2[i] != nullptr){
            actor2->attachShape(*shapes2[i]);
            //We release the shape after it has been attached such that when the actor
            // is released, the shape is also released.
            shapes2[i]->release();
        }
    }

    actor2->setMass(1);
    actor2->setCMassLocalPose(PxTransform(PxVec3(0,0,0)));
    gScene->addActor(*actor2);
    actor2->setGlobalPose(pxPose);
    actor2->setKinematicTarget(pxPose);

    //Run simulation
    gScene->simulate(dt/2);
    gScene->fetchResults(true);
    gScene->simulate(dt/2);
    gScene->fetchResults(true);

    /// OBJECT 3 with overlapping spheres

    PxArray<PxShape*> shapes3;
    for(int i = 0; i < sphere_positions.size(); i++)
    {
        //Create a sphere
        PxSphereGeometry sphereGeometry = PxSphereGeometry(0.01);
        PxShape* sphere = gPhysics->createShape(sphereGeometry, *gMaterial, true);

        //Create a box
        PxBoxGeometry boxGeometry = PxBoxGeometry(0.05, 0.05, 0.05);
        PxShape* box = gPhysics->createShape(boxGeometry, *gMaterial, true);

        //Set the position
        Vector3f pos = sphere_positions[i];
        
        sphere->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        sphere->setRestOffset(0);
        sphere->setContactOffset(1e-6);

        box->setLocalPose(PxTransform(PxVec3(pos[0], pos[1], pos[2])));
        box->setRestOffset(0);
        box->setContactOffset(1e-6);

        shapes3.pushBack(sphere);
        shapes3.pushBack(box);
    }

    //Create a kinematic actor and attach all spheres to it
    PxRigidDynamic* actor3 = gPhysics->createRigidDynamic(pxPose);
    actor3->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);

    //Attach all shapes in the object to the actor
    for(int i = 0; i < shapes3.size(); i++){
        if(shapes3[i] != nullptr){
            actor3->attachShape(*shapes3[i]);
            //We release the shape after it has been attached such that when the actor
            // is released, the shape is also released.
            shapes3[i]->release();
        }
    }

    actor3->setMass(1);
    actor3->setCMassLocalPose(PxTransform(PxVec3(0,0,0)));
    gScene->addActor(*actor3);
    actor3->setGlobalPose(pxPose);
    actor3->setKinematicTarget(pxPose);

    //Run simulation
    gScene->simulate(dt/2);
    gScene->fetchResults(true);
    gScene->simulate(dt/2);
    gScene->fetchResults(true);

    //PhysX crash when releasing the scene
    if(N >= 14){
        cout << "We are going to crash now." << endl;
    }
    PX_RELEASE(gScene);
    PX_RELEASE(gDispatcher);
    PX_RELEASE(gPhysics);
}

from physx.

adenzler-nvidia avatar adenzler-nvidia commented on July 17, 2024

Thank you very much for the detailed repro snippet - I can reproduce the crash on my machine now. Interestingly, if you run this in debug config you'll hit an assert much earlier in ScNphaseCore::resizeContactReportPairData because the paircount overflows a 16bit variable. I'll have a closer look and get back to you with a potential fix/workaround.

from physx.

adenzler-nvidia avatar adenzler-nvidia commented on July 17, 2024

Hi @PhilNad - thanks again for the repro snippet. A fix for this crash will be in the next release.

For a workaround, I suggest using more actors with each one having fewer shapes attached, such that the total number of colliding shapes per actor pair does not exceed 65536 shape pairs.

from physx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.