I’ve written height map collision detection into my game, but I’ve been struggling on how to get the resolution step to work well with player movement. (This is in 3D, by the way.)
The player is represented in the physics engine by a capsule, and the height map is essentially just a series of y-positions (heights) in a grid (2D array) representing (x,z) positions. When testing for a collision, I take all of the rectangular grid spaces that the player intersects with, then test the capsule for intersections against the two triangles that make up each grid space. (These triangle-capsule tests use the Separating Axis Theorem.) This approach allows the player to have multiple collision points, one with each triangle (e.g. one with a "ground" triangle below, keeping him from falling, and one with a "wall" triangle ahead, keeping him from walking farther forward).
However, this approach has issues. For example, if the player falls from a high place and lands on the boundary between two triangles, penetrating some distance into their faces, the direction of minimum penetration will be parallel to the ground rather than along the triangle normals. This causes the player to be pushed parallel to the ground and fall through the terrain instead of being caught.
I tried to solve this by constraining the triangles to force resolution to occur along the triangle’s normal. This solves the floor-fall problem, but introduces new problems. (There’s programming for you, huh?) For example, if the player jumps at a ledge but doesn’t make it, the triangle at the top of the ledge will still force the player upwards, causing them to be pulled up above the terrain.
Note that, since I’m using a heightmap, I don’t have any true walls and need a solution that works for slopes of any steepness. For example, the following case would also be problematic using the triangle normals as the sole basis of resolution:
At this point, I don’t know how to best take the raw collision resolution data and modify/filter it to work as I would like. How can I get these collisions to work in a sensible manner for player movement?
(It may or may not be useful to note that I currently also have a modifier on the capsule that "flattens" the resolution directions to be either parallel or orthogonal to the capsule’s local vertical direction, vertical being "from sphere to sphere." This facilitates things like allowing the player to walk up a ramp at angle without forcing them to input a diagonal direction to compensate for being pushed to the side.)