Small spheres fall through convex edges of heightfield

Issue #71 new
Steve Peters created an issue

Summary

I've noticed that spheres with a sufficiently small radius can fall through a heightfield without generating any contact points if the center of the sphere is directly above a convex edge. By a convex edge, I mean any edge shared by two heightfield triangles for which the line connecting the other vertices of these triangles (i.e. the vertices that aren't on the shared edge) lies completely within the surface.

Screen Shot 2020-10-14 at 3.34.54 PM.png

To illustrate this problem, I've modified the heightfield demo to use a convex surface and to spawn objects directly above heightfield vertices / triangulation edges. The first convex surface is a pair of inclined planes that intersect at a sharp ridge at the top (see scpeters@199c8e8b67c4). Here is a screen capture of the demo with spheres spawned directly above the ridge. You can see that spheres of small and medium size fall through the ridge without any contact, while larger spheres sink a little into the ridge while rocking back and forth along the ridge before rolling off.

spheres on sharp ridge

To illustrate with a smoother surface, I've also tested with a convex paraboloid (see scpeters@db31aaa63c), which illustrates the same behavior.

spheres on convex paraboloid

Analysis

I have investigated the dxHeightfield::dCollideHeightfieldZone function and noticed some things that may explain this behavior. This function uses multiple passes to check for collisions with a given object (hereafter referred to as sphere): with heightfield triangles treated as planes, then heightfield vertices if certain conditions are met, and finally with heightfield triangle edges (though this is disabled by a preprocessor macro by default). The first two passes are discussed below.

  1. The first pass identifies triangles that may intersect with the given sphere, computes the planes defined by each triangle, collides the sphere with each plane to generate contact points, uses the dxHeightfieldData::IsOnHeightfield2 function to determine if the given contact points lie within the appropriate bounds for the given triangle, and then culls contact points that lie outside those bounds. In the case of a sphere that is centered above a convex edge, the contact point computed between the sphere and the plane defined by each triangle lies outside the bounding box of the given triangle. For example, consider the figure below that illustrates a sphere intersecting the tip of a convex heightfield edge. The equivalent plane for the triangle on the right is illustrated by a dashed line extending from the triangle. With this geometry, the dCollideSpherePlane function places a contact point at the point of maximum depth, illustrated by the yellow circle. Since this contact point falls outside the bounding box of the triangle, it is culled by the logic in heightfield.cpp:1502-1523. A similar culling occurs for the contact point of the other intersected triangle. I believe this is a very general problem for convex edges due to the interaction of the contact points computed by dCollideSpherePlane and the contact point culling behavior based on dxHeightfieldData::IsOnHeightfield2. Screen Shot 2020-10-14 at 3.35.04 PM.png

  2. The difference between the behavior of large and small spheres may be explained by the code in heightfield.cpp:1244-1261 that sets needFurtherPasses to true if either dimension of a sphere's AABB is larger than 1.5 times the heightfield's sample width. Later, at heightfield.cpp:1557-1558, the needFurtherPasses variable is checked to determine whether the sphere should be tested for collisions with the vertices of the heightfield (pass 2). The larger spheres can be observed to not fall through the heightfield, though they do rock back and forth as they contact the different vertices.

I believe this explains why the small spheres are falling through the convex edges of the heightfield, but I'm not sure how to remedy it.

Comments (7)

  1. Oleh Derevenko

    Vertex contacts are invalid for the case of geomNDepthGetter invocation as the returned penetration depth of a point for a geometry does not mean that the penetration depth is along the plane normal.

  2. Steve Peters reporter

    thanks for the info @Oleh Derevenko; I'm reading through that old thread now and will test out the suggested code

    I wasn't able to view any of the video links, but I was able to access some pictures, and the text and code is most important

  3. Oleh Derevenko

    I’m trying to implement my own fix to the problem as well. I guess, one reason why these small object tests were not implemented initially was excessive computational cost needed to find these cases. Even with the changes already in the Git, your spheres should not fall through if you make heightfield cell size smaller than the minimum sphere size. And that could be the right approach for real application use.

  4. Steve Peters reporter

    I haven't made a video of it yet, but I've also seen problems with cylinders on convex edges. I'll have to see if colliding with vertices is enough to fix it.

  5. Log in to comment