Oh I see what is the problem, this is related cylinders with small radius.
Cylinder are expensive to calculate the closest point, for performance I added a skin thickness that is subtracted for the radius. I set to 0.05 (that's about 2 index)
but is a cylinder has a radius that is comparable to the skin thickness, them some edge contact will not be close to he ideal contact on the cylinder surface.
In you test the cylinder radius is 0.1 why si 50% of the thickness and that make the contact solver find edge contacts that will be till more than 45 degree even when rolling on a flat surfaces
after lot of debugging I reliance that nothing was wrong, yes I was getting this estrange contacts far away from the outside form the cinder surface and they where never rejects, until I realize that all contact were very close. the I say tan the cylinder had a small radios compared to the tolerance.
so as a test I set the tolerance smaller, and the made it better at the expense of going to the more expensive contact routine each time.
I check it is like that. Late I will made the tolerance a member for the cylinder class, that way if can be a calculated and truncated value.
so that Large cylinder can have a larger tolerance and use the fast routine and small cylinder will have the smaller tolerance.
ironically had the cylinder being smaller than the tolerance it would work, because the code only use the tolerance on cylider with radius larger that the tolerance
- Code: Select all
dgVector dgCollisionCylinder::ConvexConicSupporVertex (const dgVector& dir) const
{
dgAssert (dgAbsf ((dir % dir - dgFloat32 (1.0f))) < dgFloat32 (1.0e-3f));
dgFloat32 radius = (m_radius > DG_CYLINDER_SKIN_PADDING) ? m_radius - DG_CYLINDER_SKIN_PADDING : m_radius;
dgFloat32 height = (m_height > DG_CYLINDER_SKIN_PADDING) ? m_height - DG_CYLINDER_SKIN_PADDING : m_height;
dgFloat32 y0 = radius;
please try again. with the setting should be much better now. It will never be ideally perfect as long as the cylinder uses a skin tolerance. but I do no know of any algorithm that allow the calculation of the closest distance form a cylinder to some other primitive that does no requires a skin distance.
they can get the distance when the do not interpenetrate, or when the interpenetrate, but they fail when the primitive are simply touching. so you have to use hysteresis. make the cylinder smaller when testing for no intergeneration, and make the cylinder larger if the first test fail and test for interpenetration.
It on the gray area that the contact may not represent the ideal contact 100%.
when the distance tolerance is small relative to the size of the shapes, then is not problem but when the shape is comparable to the distance tolerance then the error become significant.
The other problem is that the error can no be made arvitrally small. because then when the tow shape are close the algorithm start losing floating point integrate too fast.
This is the biggest problem I have with JGK, it Is too numerically unstable, but on the other hand it I the best game in town for calculating distance between convex shapes.