ODE heightfield-sphere collision patch (C) 2011 Erik Schuitema The main problem with collision detection between spheres and a heightfield lies in the fact that up to now, contacts were only generated when a collision contact was located within the triangle's area. The first fix involved projecting the contact (positioned under the plane) back onto the plane to avoid problems on the upper edges of rising triangles. After this fix, there's still a 'dead zone' for convex triangle edges. The (only?) fix for this is to detect collisions between the triangle's edge and the geom. In the existing code, this was done using ray detection, but this principally does not give the desired contact location. So new collision detectors have to be written (already available in the trimesh code!) for collisions with segments. The following things were changed in heightfield.cpp to have proper collision detection with spheres: Line 69) Edge collision detection is essential in order to not have spheres fall through concave triangle edges. Therefore, it is always enabled. Line 71) Vertex collision detection has been disabled, because it's useless when edge collision detection is enabled. Line 1088) Renamed geomRayNCollider to geomNSegmentCollider, since we need segment collision detection, not ray collision detection. Line 1286) Enabled 'needFurtherPasses' by default for spheres. Probably should be enabled for all geoms. Line 1546) The position of a detected contact with a plane is projected back onto that plane before detecting whether the contact is above a certain triangle with IsOnHeightfield2(). This assures continuous collision behavior when moving from a plane to an edge between planes. Line 1708) vertex1 was erroneously taken as starting position of the ray - should be vertex0 Line 1718) Disabled further processing of a segment contact because the segment collider (at least for spheres) already returns the proper contact (pos, normal, depth). Line 1744) Do not set vertex state to true after processing a triangle edge, since a vertex is shared between many edges. This can possibly be replaced by a true 'segment processed' state to speed things up. Now probably many edges are checked twice.