PhysX contacts generation bug

Hello! We in our project has encountered a bug in PhysX contacts generation. We have to planar objects in small separation distance and throw small bullet to one of them. Contacts are generated sometime with front object, sometime with back object, ignoring front of them. CCD is enabled for all of object. Here is PhysxVisualDebugger recording: [url]https://drive.google.com/file/d/0B1SCg9e5O89zSmNVc2hPZE9WNFU/view?usp=sharing[/url]. First shot is ok, two are bad, last is ok. We are using latest PhysX from git (https://github.com/NVIDIAGameWorks/PhysX-3.3). Can anyone hel us with this, please?

Here is one more PVD with bugs in two objects on small distance. We are shooting to front object and getting contacts in absolutely wrong place (right up corner of front object). [url]https://drive.google.com/file/d/0B1SCg9e5O89zVFZtWFNyaV8xUTQ/view?usp=sharing[/url]

No answers, gameworks techsupport don’t answer as well. Looks like - “it is now open source, so fix it by yourself”, and it is sad, as I have no idea about mathematics and architecture of PhysX(, as there is no available documents about it’s internal structure.

And GPU libraries are still closed source, it prevents me from compiling PhyX for VS2015…

Great support!

Up

Could you explain why the target is made of 3 shapes? In pvd I can see that it is made of two convexes and a box. I suspect that simplifying your geometry will help here.

Your scene is going to be very hard to resolve, even with ccd enabled. The bullet is only millimetres in scale and moves at around 300 metres per second at a target that is about 1cm thick. This is a really hard problem.

Typically, games use scene queries to model bullet collisions. There is really no point in modelling the pre-impact flight of the bullet because the time between pulling the trigger and the impact is much less than one frame. Instead, just issue a scene query along the direction of the bullet and use the result to add the bullet to the scene at the coordinate of the scene query hit with a well-chosen velocity.

Cheers,

Gordon

We are developers of shooting simulator. Box is detachable part, convex shapes are generated by 3ds max plugin, so complexity is invariant. We change initial speed of bullet and shooting distance dynamically - on a 1 km distance with a wind ballistics are relevant, so ray cast scene queries is a bad simplification in such case. So, as I understood your words - such behavior is normal by design, it is not a bug, so it could not be fixed? Looks like we have a serious problems…

I didn’t say if it was likely to be a bug or not. It is very hard to tell. My point was only that the scene you have is better handled with scene queries. I still maintain that this is the case. With a little scene management in your game code you will get much better performance from physx if you use scene queries. For example, you are updating physx with a timestep of 1/120. This isn’t really small enough to model the speeds and objects scales you have. Decreasing the timestep further, however, is not worth the extra overhead because it is hard to tell visually what is correct physics and what is not. Not using scene queries is a a bit of a waste of cpu, to be honest.

At the start of each frame you know the position and velocity of the bullet and the timestep of the next update. This tells you the start and end point of the bullet over the frame. If the bullet starts at P0 and we assume that the bullet hits nothing over frame then at the end of the update the bullet will have position P1

P1 = P0 + velocity * timestep

All you have to do is issue a raycast between P0 and P1. If the raycast hits nothing then you just update the bullet’s coordinate in your game to P1 and render it there. If the bullet hits something then the bullet will be given the coordinate of the hit point returned by the raycast. The bullet will be rendered at the hit point. In pseudo-code the bullet update code will be as follows:

P1 = P0 + velocity * timestep;
bool hitsomething = raycast(P1, P2, &hit);
if(hitSomething)
{
P1 = hit.position;
}
renderBullet(P1);

If you want the bullet to bounce off the hit point and fall to the ground then you can add a rigid body to the physx scene and set it to be a kinematic. Each frame you will set the kinematic target to be P1. When the bullet hits something you just lower the kinematic flag and set its velocity and position as appropriate. PhysX will control the bullet for all subsequent frames. The pseudo-code above can be adapted for this extra step:

if(isKinematic(bullet))
{

P1 = P0 + velocity * timestep;
bool hitsomething = raycast(P1, P2, &hit);
if(hitSomething)
{
   P1 = hit.position;
   setKinematic(bullet, false);
   setPosition(bullet, hit.position);
   setVelocity(bullet, hit.normal*magnitude(getVelocity(bullet))*0.001f;
}
else
{
   setKinematicTarget(bullet, P1);
}

}
renderBullet(P1);

Cheers,

Gordon

One more comment regarding the multiple shapes of the target. I don’t really see the advantage of having multiple shapes. If you added a single thin box for the bullet to collide with you will see the same behaviour but with much less cost. The physx query and simulation filtering systems can be used to decide what collides with what. If you want some of the shapes to be activated when the bullet hits the target then you can use the variable hitsomething in the pseudo-code of my previous post to start their motion.

Cheers,

Gordon

More info on this problem (looks like it is the same problem) - we use such code (1 hit) for two rigidstatics, ground trianglemesh and rock convex on it:

PxQueryFlags Flags(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC);
PxRaycastHit* HitsArray = new PxRaycastHit[1];
PxRaycastBuffer Hits(HitsArray, 1);
if(pScene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), dst, Hits, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlags(Flags))))
{...}

Code gives us only ground hit, which is not nearest. If we call such code (2 hits):

PxQueryFlags Flags(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC);
Flags |= PxQueryFlag::eNO_BLOCK;
PxRaycastHit* HitsArray = new PxRaycastHit[2];
PxRaycastBuffer Hits(HitsArray, maxcount);
if(pScene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), dst, Hits, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlags(Flags))))
{...}

We get array with 2 hits, first is ground with dst = 254, and second is rock with dst = 250.

Here we can use sort for hits by the dst and use first, ok. But what to do with our initial problem, there collision with overlapped objects is reported in wrong order, we don’t know… if this is connected problems, of course.

Here is PVD with bug, look to scene queryes:
https://drive.google.com/file/d/0B1SCg9e5O89zbjdDbFNjMmVjUEU/view?usp=sharing