Reverend Speed
Reverend Speed

Reputation: 215

How do I get a 3D collision with a Heightmap in Raylib?

I'm presently trying to do a sorta Starfox clone with Raylib, using the heightmap example here: https://www.raylib.com/examples/models/loader.html?name=models_heightmap

In order to handle collision in this environment, I think we need to check the player's current height against the grey value of the current pixel the craft is within. If the grey value of the currently 'occupied' ground pixel is 'higher' than the player's current Y, then the plane is currently touching the ground and has crashed.

Heightmap Illustration In my illustration, we'll assume that if the player is at the height level indicated by C05 in that box, then they're in contact with the ground and is crashing. However, if the player is at the height of total white while positioned on a black square (XZ), eg. B04, then they're high over the canyon and not colliding.

I can't seem to work out how to identify the right pixel in the heightmap to match the player's position from within Raylib - does anybody know how to extract that info?

Upvotes: 1

Views: 45

Answers (1)

Reverend Speed
Reverend Speed

Reputation: 215

Turns out, it's reasonably easy to normalise world coords, apply that to image UV, get the heightmap brightness, normalise those, multiply by world height and then test against player position.

// Get Normalised Coord
float worldNormalX = (playerPosition.x + abs(mapPosition.x)) / mapSize.x;
float worldNormalZ = (playerPosition.z + abs(mapPosition.z)) / mapSize.z;
float texUcoord = worldNormalX * texture.width;
float texVcoord = worldNormalZ * texture.height;

// Clampity clamp (make this a helper function?) 0.001f - just to be sure we don't get OOBounds error
if (texUcoord > texture.height - 0.001f) texUcoord = texture.height - 0.001f;
if (texUcoord < 0) texUcoord = 0;

if (texVcoord > texture.width - 0.001f) texVcoord = texture.width - 0.001f;
if (texVcoord < 0) texVcoord = 0;

Color colorFromPosition = GetImageColor(image, texUcoord, texVcoord);
float worldYNormalFromCol = colorFromPosition.r / 255.0f;
float worldYPos = worldYNormalFromCol * mapSize.y;

playerPosition.y = worldYPos;

Hope this is useful to someone.

Upvotes: 0

Related Questions