We are experiencing an issue where a sphere (with a simple sphere collision and CCD enabled) is colliding at high velocity with a surface. CCD works in the sense that the sphere is not passing through the other object. But the sphere does penetrate the surface up to a point before bouncing back.
Here is a screenshot taken when the HitEvent is triggered (made in Unreal with just the simple assets from the 1st person template):
The setup: The sphere is falling from 15 meters with 10 times normal gravity force (these values are exaggerations but the issue does occur with smaller values too). It collides with 2 static cubes that are right next to each other.
In this case, because the sphere penetrates through the cube on the right, it also collides with the edge of the cube on the left, causing it to bounce to the right instead of straight up.
Any idea on how I can reduce this penetration distance ?
I’ve tried increasing the number of max CCD passes in the scene constructor from ScScene.cpp. Also tried playing around with mCore.ccdAdvanceCoefficient in BodyCore constructor from ScBodyCore.cpp. None of these seem to have done much.
Thanks a lot!
Can you provide a PVD capture of this scene?
You can find a capture here:
I think that I figured out the problem. Basically, CCD is only performed on fast-moving pairs, even if the objects have the CCD flag enabled.
threshold0 = sc0->geometry.computeBoundsWithCCDThreshold(origin, extents, tm0, NULL);
threshold1 = sc1->geometry.computeBoundsWithCCDThreshold(origin, extents, tm1, NULL);
const PxReal thresh = threshold0 + threshold1;
//If no shape pairs in the entire scene are fast-moving, we can bypass the entire of the CCD.
needsSweep = needsSweep || (trA - trB).magnitudeSquared() >= (thresh * thresh);
There are a few more checks like that spread out throught the CCD code. So the threshold is based on the return of computeBoundsWithCCDThreshold which in the case of a sphere is 0.75 * radius.
So basically in my case, the code decided that CCD wasn’t needed for the sphere collision, because there was no chance of it tunneling through the cubes.
If I replace the 0.75 used for the bounds with 0.01, CCD sweeps get triggered and the collision behaves the way that it should. But I’m not sure that changing computeBoundsWithCCDThreshold is the correct way to go because it’s also being used in PxsAABBManagerAux.cpp
I might change the way that the CCD sweep thresholds are computed in PxsCCD.cpp
There are performance and stability risks if you adjust the CCD thresholds too low. By all means, reduce them if it helps but I would strongly recommend not using any settings that trigger CCD to be active at low velocities (e.g. when a shape is just resting/sliding gently on the ground). If CCD becomes active at these low speeds, this will potentially lead to artefacts. If you set the threshold to half its default, that’s probably OK. However, setting it to 0.01 * radius will more likely than not lead to artefacts when you are working with more complex cases. If you adjust the calculations in PxsCCD.cpp, you could potentially half the thresholds, use the min of the 2 shapes’ thresholds rather than the sum of them or a combination of the 2.
Looking at the PVD capture, it appears that contact offset on the sphere is extremely low (0.48). The same is the case on the convex boxes that it’s colliding against, which have contact distance of 0.5. Given that UE4 uses cm units, this is ~0.5cm contact offset for each shape. By default, PhysX uses 2cm of contact offset per-shape, which would mean that contacts are generated as soon as shapes get within 4cm of each-other. With the current settings, this doesn’t happen until they’re within 1cm of each-other. If distant contacts are generated, this acts similar to CCD to stop objects becoming penetrated (a separation is detected and then the solver ensures the shapes don’t become penetrated).
The 2cm default offsets are appropriate for roughly Earth gravity (-9.8m/s). In addition, there is BounceThresholdVelocity that is configured to 2m/s, which is also appropriately configured for Earth-like gravity. If stronger gravity is used, it may be necessary to increase these thresholds to compensate for this otherwise objects may struggle to come to rest.
Performance shouldn’t be an issue for us since we’re going to have a single movable object with CCD enabled in our game. But artefacts might indeed be a problem. I will try to reduce the threshold combined with an increase in the contact offset that you mentioned.
Setting the gravity to a high value was just for illustration purposes, to be able to reproduce the issue consistently. But we’ve been experiencing the issue 1/5 using regular gravity(9.8m/s), and a 10cm sphere falling from a height of 50cm. Tends to happen more with lower fps.
Thanks for the help.
If you’re simulating using variable time-steps (e.g. at whatever rate is being rendererd), then that could also cause issues. Wherever possible, elect for fixed timesteps, e.g. simulating at 1/60 or something similar.